sql >> Databáze >  >> RDS >> Database

Vytvoření dynamické kontingenční tabulky s funkcí QUOTENAME

V mém předchozím článku o základním kontingenčním operátoru jsme viděli, jak lze kontingenční operátor použít k převodu řádků na sloupce, což vede k kontingenčním tabulkám. Viděli jsme, že k vytvoření kontingenční tabulky existují tři hlavní kroky. Prvním krokem byl výběr základních dat. Druhým krokem byl převod základních dat na výraz s tabulkovou hodnotou a poslední krok zahrnoval použití kontingenčního operátoru na dočasná data, což vedlo ke kontingenční tabulce.

Podívejte se na příklad níže.

USE schooldb

SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN ([London],[Liverpool],[Leeds],[Manchester])
) AS StudentPivotTable

Poznámka: Chcete-li vytvořit fiktivní databázi a data, přečtěte si předchozí článek o Pivot Operator.

Omezení Pivot Operator

Existují však určitá omezení pivotového operátora. Uvnitř pivotového operátoru musíme specifikovat agregované pole a sloupce, podle kterých chceme naše data pivotovat. Nakonec musíme také nastavit jednotlivé hodnoty pro záhlaví sloupců, které chceme vytvořit.

Pokud bychom provedli skript z předchozí sekce, dostali bychom následující výsledek:

[id tabulky=35 /]

Záhlaví sloupců jsou jednotlivé hodnoty uvnitř sloupce města. Tyto hodnoty jsme specifikovali uvnitř pivotního operátoru v našem dotazu.

Nejnáročnější částí vytváření kontingenčních tabulek je ruční zadávání hodnot pro záhlaví sloupců. Toto je část, která je náchylná k většině chyb, zejména pokud se změní data ve vašem online zdroji dat. Nemůžeme si být jisti, že hodnoty, které jsme zadali v kontingenčním operátoru, zůstanou v databázi, dokud tuto kontingenční tabulku příště nevytvoříme.

V našem skriptu jsme například zadali Londýn, Liverpool, Leeds a Manchester jako hodnoty pro nadpisy naší kontingenční tabulky. Tyto hodnoty existovaly ve sloupci Сity tabulky studentů. Co když dojde k odstranění nebo aktualizaci jedné nebo více těchto hodnot? V takových případech bude vrácena hodnota null.

Lepším přístupem by bylo vytvořit dynamický dotaz, který vrátí úplnou sadu hodnot ze sloupce, ze kterého se pokoušíte vygenerovat kontingenční tabulku.

Vytvoření dynamické kontingenční tabulky

V této části uvidíme, jak vytvořit dynamickou kontingenční tabulku.

To znamená, že nebudeme muset ručně zadávat hodnoty pro sloupec, ze kterého se pokoušíme vygenerovat naši kontingenční tabulku. Místo toho nastavíme tyto hodnoty dynamicky. K tomuto účelu použijeme funkci „QUOTENAME“.

Jako vždy se před experimentováním s novým kódem ujistěte, že máte dobrou zálohu. Pokud si nejste jisti, přečtěte si tento článek o zálohování databází MS SQL.

Funkce QUOTENAME

Funkce „QUOTENAME“ formátuje vybrané výsledky. Před vysvětlením dynamického pivotu stojí za to podívat se na rychlý pracovní příklad funkce „QUOTENAME“.

Podívejte se na následující dotaz.

USE schooldb

SELECT QUOTENAME(city)+ ','
FROM student

Ve výchozím nastavení funkce „QUOTENAME“ zalomí vybrané položky do hranatých závorek. Výstup výše uvedeného dotazu vypadá takto:

[id tabulky=36 /]

Ukládání názvů sloupců do proměnné

Přestože jsme zabalili hodnoty sloupců do hranatých závorek, musíme hodnoty v kontingenčním operátoru zadat v tomto formátu:

“[Leeds],[Liverpool],[Londýn],[Manchester]”

K tomu budeme potřebovat proměnnou.

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

PRINT @CityNames

Ve výše uvedeném dotazu jsme deklarovali proměnnou „@CityNames“ a inicializovali ji prázdným řetězcem. Poté jsme pomocí příkazu SELECT vybrali odlišná jména měst ze sloupce města a uložili je iterativně do proměnné „@CityNames“. V každé iteraci bude k proměnné „@CityNames“ přidána odlišná hodnota ve sloupci města spolu s čárkou.

Poté jsme vytiskli hodnotu uloženou v této proměnné. Výsledek výše uvedeného dotazu bude vypadat takto:

“[Leeds],[Liverpool],[Londýn],[Manchester],”

Pokud se podíváte na výstup, za poslední hodnotou je čárka. To nepotřebujeme.

Odstranění čárky na konci

Chcete-li odstranit koncovou čárku, použijeme funkci LEFT, která jako svůj první argument vezme řetězec. Druhý argument je počet znaků, které mají být vráceny z tohoto řetězce počínaje prvním znakem. Podívejte se na následující dotaz:

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

PRINT @CityNames

Zde věnujte pozornost tomuto řádku skriptu:

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

V tomto řádku skriptu jsme pomocí funkce LEFT získali všechny znaky na levé straně hodnoty uložené v proměnné „@CityNames“, počínaje prvním prvkem. Ve druhém argumentu jsme pomocí funkce LEN vypočítali počet hodnotových prvků uložených ve funkci „@CityNames“ a nakonec jsme od něj odečetli 1. Tím se z řetězce odstraní koncová čárka. Výstup bude vypadat takto:

[Leeds], [Liverpool], [Londýn], [Manchester]

Převod SQL dotazu na řetězec

Nyní, doufejme, můžeme v našem pivotním operátoru použít proměnnou „@CityNames“ takto:

PIVOT(
	AVG(total_score)
	FOR city IN ( @CityNames )

Nemůžeme však použít proměnnou uvnitř našeho pivotního operátoru. Alternativním přístupem je převedení našeho kompletního SQL dotazu na řetězec. Uvnitř tohoto řetězce zavěsíme naši proměnnou „@CityNames“.

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''
DECLARE @Query NVARCHAR(MAX) = '' 

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

SET @Query =
'SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN (' + @CityNames +')
) AS StudentPivotTable'

PRINT @Query

Zde jsme deklarovali proměnnou „@Query“ a do této proměnné uložili náš SQL dotaz. Uvnitř pivotového operátoru jsme zřetězili hodnotu uloženou uvnitř proměnné „@CityNames“. Abychom viděli, jak provedený dotaz vypadá, vytiskli jsme hodnotu proměnné „@Query“. Výsledný dotaz bude ve výstupu vypadat takto:

SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN ([Leeds],[Liverpool],[London],[Manchester])
) AS StudentPivotTable

To je přesně ten typ dotazu, který chceme provést. Toto je však ve formátu String. Posledním krokem je provedení tohoto SQL dotazu uloženého jako textový řetězec. K tomu použijeme Dynamic SQL.

Provádění dynamického SQL

Ke spuštění dynamického SQL používáme vestavěnou proceduru „sp_executesql“. Tuto uloženou proceduru použijeme ke spuštění dotazu uloženého v proměnné @Query. Náš poslední dotaz, který vytvoří dynamickou kontingenční tabulku, vypadá takto:

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''
DECLARE @Query NVARCHAR(MAX) = '' 

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

SET @Query =
'SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN (' + @CityNames +')
) AS StudentPivotTable'

EXECUTE sp_executesql @Query

Po provedení výše uvedeného dotazu byste měli vidět následující výsledek:

[id tabulky=37 /]

Tentokrát jsme však ručně nespecifikovali hodnoty pro nadpisy kontingenční tabulky. Místo toho byly nadpisy vypočítány dynamicky a výsledkem je dynamická kontingenční tabulka.


  1. Jak integrovat Oracle a Kafka

  2. 6 způsobů, jak přidat měsíc k datu v MariaDB

  3. Jak převést celé číslo na desítkové v SQL Server

  4. Jak přidat vertikální okraje do vaší výstupní mřížky SQL*Plus / SQLcl