Grupowanie wielowymiarowe w MS SQL Przykładowe dane
Feb 04, 2016
Grupowanie wielowymiarowe w MS SQL Przykładowe dane
Tworzymy widok
USE [buczek]GO/****** Object: View [dbo].[Sprzedaz] Script Date: 11/25/2007 11:32:07 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE VIEW [dbo].[Sprzedaz]ASSELECT dbo.ds_Asortymenty.NazwaAsortymentu, dbo.tch_ListaProduktow.Wymiar, dbo.ds_klienci.Nazwa, dbo.ha_Zamowienie.DataZamowienia, dbo.ha_ZamLinie.IloscFROM dbo.ds_klienci INNER JOIN dbo.ha_Zamowienie ON dbo.ds_klienci.Id = dbo.ha_Zamowienie.IdKlienta INNER JOIN dbo.ha_ZamLinie ON dbo.ha_Zamowienie.IdZamowienie = dbo.ha_ZamLinie.IdZamowienie INNER JOIN dbo.ds_Asortymenty INNER JOIN dbo.tch_ListaProduktow ON dbo.ds_Asortymenty.IdAsortymentu = dbo.tch_ListaProduktow.IdAsortymentu ON dbo.ha_ZamLinie.IdProduktu = dbo.tch_ListaProduktow.IdProduktu
GO
SELECT NazwaAsortymentu, Nazwa, SUM(Ilosc) AS RazemFROM dbo.SprzedazGROUP BY NazwaAsortymentu, NazwaORDER BY NazwaAsortymentu
SELECT NazwaAsortymentu, Nazwa, SUM(Ilosc) AS RazemFROM SprzedazGROUP BY NazwaAsortymentu, Nazwa WITH CUBE
Zastępowanie wartości null
Funkcja GROUPING zwraca 1 jeśli wartość null jest wynikiem działania operatora CUBE klauzuli GROUP BY i 0 jeśli null jest wynikiem braku danych
Funkcja ISNULL zastępuje null podaną wartością
SELECT CASE WHEN (GROUPING(NazwaAsortymentu) = 1) THEN 'Razem' ELSE ISNULL(NazwaAsortymentu, 'Nieznana') END AS Asortyment, CASE WHEN (GROUPING(Nazwa) = 1) THEN 'Razem' ELSE ISNULL(Nazwa, ‘Nieznana') END AS Firma, SUM(Ilosc) AS IloscRazemFROM dbo.SprzedazGROUP BY NazwaAsortymentu, Nazwa WITH CUBE
Podsumowania jednowymiarowe
SELECT CASE WHEN (GROUPING(NazwaAsortymentu) = 1) THEN 'Razem' ELSE ISNULL(NazwaAsortymentu, 'Nieznana') END AS Asortyment, SUM(Ilosc) AS IloscRazemFROM dbo.SprzedazGROUP BY NazwaAsortymentu WITH CUBE
Perspektywa umożliwia dowolne przeglądanie podsumowań
USE [buczek]GO/****** Object: View [dbo].[SprzedazCube3] Script Date: 11/27/2007 15:45:27 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE VIEW [dbo].[SprzedazCube4]ASSELECT CASE WHEN (GROUPING(NazwaAsortymentu) = 1) THEN 'Razem' ELSE ISNULL(NazwaAsortymentu, ' Nieznana ') END AS Asortyment, CASE WHEN (GROUPING(Nazwa) = 1) THEN 'Razem' ELSE ISNULL(Nazwa, ' Nieznana ') END AS Firma, SUM(Ilosc) AS IloscRazemFROM dbo.SprzedazGROUP BY NazwaAsortymentu, Nazwa WITH CUBE
GO
SELECT Asortyment, IloscRazem, FirmaFROM dbo.SprzedazCube4WHERE (Asortyment = 'A-Rura z/s aluminiowana gładka') AND (Firma = 'Razem')
Transact - SQL
Pracochłonne zapytania np. aktualizujące dane można zastąpić procedurami składowanymi
use buczekSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO
CREATE PROCEDURE Dopisywanie
@Nazwa char(255), @KodPocztowy char(255),@Miejscowosc char(255)
ASBEGIN
insert into ds_klienci (Nazwa, KodPocztowy, Miejscowosc) values (@Nazwa, @KodPocztowy, @Miejscowosc)ENDGO
dopisywanie 'Firma A', '30-150', 'Kraków'
Kursor
Kursor jest tabelą rekordów umożliwiającą dostęp do kolekcji pobranej z tabeli lub złożenia
USE buczekGO-- Execute the SELECT statement alone to show the -- full result set that is used by the cursor.SELECT Nazwa, Miejscowosc FROM ds_klienciORDER BY Nazwa-- Declare the cursor.DECLARE kursor SCROLL CURSOR FORSELECT Nazwa, Miejscowosc FROM ds_klienciORDER BY NazwaOPEN kursor-- Fetch the last row in the cursor.FETCH LAST FROM kursor-- Fetch the row immediately prior to the current row in the cursor.FETCH PRIOR FROM kursor
-- Fetch the second row in the cursor.FETCH ABSOLUTE 2 FROM kursor-- Fetch the row that is three rows after the current row.FETCH RELATIVE 3 FROM kursor-- Fetch the row that is two rows prior to the current row.FETCH RELATIVE -2 FROM kursorCLOSE kursorDEALLOCATE kursorGO
Wykorzystanie kursora
SELECT DataZamowienia, SUM(DISTINCT Ilosc) AS razemFROM SprzedazGROUP BY DataZamowieniaORDER BY DataZamowienia
USE buczekGODECLARE @Il real, @Poprzedni real, @Dynamika realDECLARE kursor CURSOR FORSELECT SUM(DISTINCT Ilosc) AS razemFROM SprzedazGROUP BY DataZamowieniaORDER BY DataZamowieniaOPEN kursorFETCH NEXT FROM kursorINTO @PoprzedniWHILE @@FETCH_STATUS = 0BEGIN FETCH NEXT FROM kursor INTO @Il PRINT @Il PRINT @Poprzedni PRINT @Il/@Poprzedni SET @Poprzedni=@IlEND
Dopisywanie rekordów i identyfikacja klucza
USE [Test]GO/****** Object: StoredProcedure [dbo].[InsertZamowienie] Script Date: 11/27/2007 18:58:44 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [dbo].[InsertZamowienie] @Klient char(255), @Data datetime, @Identity bigint ASDECLARE @IdKlienta bigintSELECT @IdKlienta = IdKlienta FROM KlienciWHERE Nazwa = @KlientINSERT INTO Zamowienia (Data, IdKlienta) VALUES(@Data, @IdKlienta)SET @Identity = SCOPE_IDENTITY()Print @Identity
Uruchomienie procedurySET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE Test ASDECLARE @indeks bigintbeginexec InsertZamowienie 'Firma AS', '2007-11-30', @indeksPRINT @indeksend
Przykład
Fabryka rur stalowych produkuje rury z kręgów blachy stalowej w następujących operacjach– rozcięcie kręgu (coil cut)– perforowanie (perforating) – tylko dla rur perforowanych– zgrzewanie
Zamówienia składają się z wielu linii Dla każdej wprowadzonej linii należy opracować
kartę technologiczną (Product card)
Wyzwalacze
W tabeli OrderLine po wpisaniu nowego zamówienia automatycznie uzupełniamy pole Status wartością „1”
po opuszczeniu linii:
„Uzbrajanie” linii zamówienia
Każda linia zawiera identyfikator produktu finalnego
Opis wszystkich faz procesu zapisany jest w tabeli ProductionPlan, przy czym IdStock jest identyfkatorem półproduktu opisanego w tabeli Product
Ze względu na iterację nie można wygenerować opisu technologii dla linii zamówienia przy pomocy prostego zapytania SQL
Diagram i zawartość linii zamówień
Diagram powiązań opisu technologii
Wykorzystanie Transact-SQL
Język Transact-SQL wprowadza elementy języków proceduralnych takich jak pętla, warunek logiczny, zmienna pamięciowa
Przykładowa procedura odszukuje w tabeli ProductionPlan wiersz dla operacji, której wynikiem jest wyrób gotowy a następnie w pętli szuka kolejnych półproduktów aż do chwili gdy zapytanie SELECT nie zmienia wartości indeksu półproduktu (@adress1)
declare @adress bigint, @adress1 bigint, @stock real, @yield realSELECT TOP 1 @adress1=ProductionPlan.IdStock,@adress=OrderLine.IdProduct,
@stock=OrderLine. Quantity, @yield=ProductionPlan.YieldFROM OrderLine INNER JOIN Product ON OrderLine.IdProduct = Product.IdProduct INNER JOIN ProductionPlan ON Product.IdProduct = ProductionPlan.IdProduct WHERE orderline.status=1print 'Ordered product Id:'Print @adressprint 'First semiproduct Id:'print @adress1print 'Yield:'print @yieldset @stock=@stock/@yieldprint 'Stock for first operation:'print @stockwhile @adress1 <> @adressbegin
set @adress=@adress1SELECT @adress1=ProductionPlan.IdStockFROM ProductionPlanWHERE ProductionPlan.IdProduct=@adressSELECT @yield=ProductionPlan.YieldFROM ProductionPlan WHERE ProductionPlan.IdProduct=@adressif @adress1<> @adress begin
set @stock=@stock/@yieldprint 'Next semiproduct Id:'print @adress1print 'Yield:'print @yieldprint 'Stock for next operation:'print @stock
endend
Ordered product Id:43First semiproduct Id:999Yield:0.95Stock for first operation:62.1053Next semiproduct Id:937Yield:0.9Stock for next operation:69.0059Next semiproduct Id:1781Yield:1Stock for next operation:69.0059
Tworzenie karty technologicznej
Do tabeli ProductCard dopisywane są kolejne rekordy opisujące operacje w ciągu technologicznym
declare @adress bigint, @adress1 bigint, @orderid bigint, @stock real, @yield real,@operation bigint,@tool bigint,@unit bigint, @productivity real
SELECT TOP 1 @adress1=ProductionPlan.IdStock,@adress=OrderLine.IdProduct, @stock=OrderLine. Quantity, @yield=ProductionPlan.Yield,@orderid=OrderLine.IdOrderLine, @operation=ProductionPlan.IdOperation,@tool=ProductionPlan.IdTool, @unit=ProductionPlan.IdUnit,@productivity=ProductionPlan.Productivity
FROM OrderLine INNER JOIN Product ON OrderLine.IdProduct = Product.IdProduct INNER JOIN ProductionPlan ON Product.IdProduct = ProductionPlan.IdProduct WHERE orderline.status=1INSERT INTO ProductCard (IdOrderLine, IdOperation,IdTool,IdUnit,Productivity,Yield,IdStock)VALUES (@orderid, @operation, @tool, @unit, @productivity, @yield, @adress1)set @stock=@stock/@yieldwhile @adress1 <> @adressbegin
set @adress=@adress1SELECT @adress1=ProductionPlan.IdStock, @yield=ProductionPlan.Yield,
@operation=ProductionPlan.IdOperation,@tool=ProductionPlan.IdTool, @unit=ProductionPlan.IdUnit,@productivity=ProductionPlan.Productivity
FROM ProductionPlan WHERE ProductionPlan.IdProduct=@adressif @adress1<> @adress begin
INSERT INTO ProductCard (IdOrderLine, IdOperation,IdTool,IdUnit,Productivity,Yield,IdStock)
VALUES (@orderid, @operation, @tool, @unit, @productivity, @yield, @adress1)
set @stock=@stock/@yieldend
end