Database
 sql >> Baza danych >  >> RDS >> Database

Tworzenie dynamicznej tabeli przestawnej z funkcją QUOTENAME

W moim poprzednim artykule na temat podstawowego operatora przestawnego widzieliśmy, jak można go użyć do konwersji wierszy na kolumny, czego wynikiem są tabele przestawne. Widzieliśmy, że tworzenie tabeli przestawnej składało się z trzech głównych kroków. Pierwszym krokiem było wybranie danych bazowych. Drugim krokiem było przekonwertowanie danych bazowych na wyrażenie z wartościami przechowywanymi w tabeli, a ostatnim krokiem było zastosowanie operatora przestawnego do danych tymczasowych, co zaowocowało powstaniem tabeli przestawnej.

Spójrz na poniższy przykład.

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

Uwaga: Aby utworzyć fikcyjną bazę danych i dane, zapoznaj się z poprzednim artykułem na temat operatora przestawnego.

Ograniczenia operatora przestawnego

Istnieją jednak pewne ograniczenia operatora obrotu. Wewnątrz operatora przestawnego musimy określić pole zagregowane i kolumny, na których chcemy przestawić nasze dane. Na koniec musimy również ustawić indywidualne wartości dla nagłówków kolumn, które chcemy utworzyć.

Gdybyśmy wykonali skrypt z poprzedniej sekcji, otrzymalibyśmy następujący wynik:

[identyfikator tabeli=35 /]

Nagłówki kolumn to poszczególne wartości w kolumnie miasta. Określiliśmy te wartości wewnątrz operatora przestawnego w naszym zapytaniu.

Najbardziej żmudną częścią tworzenia tabel przestawnych jest ręczne określanie wartości nagłówków kolumn. Jest to część, która jest podatna na większość błędów, zwłaszcza jeśli zmienią się dane w źródle danych online. Nie możemy być pewni, że wartości określone w operatorze przestawnym pozostaną w bazie danych, dopóki nie utworzymy tej tabeli przestawnej następnym razem.

Na przykład w naszym skrypcie określiliśmy Londyn, Liverpool, Leeds i Manchester jako wartości nagłówków naszej tabeli przestawnej. Te wartości istniały w kolumnie Miasto w tabeli uczniów. Co się stanie, jeśli w jakiś sposób co najmniej jedna z tych wartości zostanie usunięta lub zaktualizowana? W takich przypadkach zostanie zwrócony null.

Lepszym rozwiązaniem byłoby utworzenie dynamicznego zapytania, które zwróci pełny zestaw wartości z kolumny, z której próbujesz wygenerować tabelę przestawną.

Tworzenie dynamicznej tabeli przestawnej

W tej sekcji zobaczymy, jak utworzyć dynamiczną tabelę przestawną.

Oznacza to, że nie będziemy musieli ręcznie określać wartości dla kolumny, z której próbujemy wygenerować naszą tabelę przestawną. Zamiast tego ustawimy te wartości dynamicznie. W tym celu użyjemy funkcji „NAZWA KWOTOWANIA”.

Jak zawsze, upewnij się, że masz dobrą kopię zapasową, zanim zaczniesz eksperymentować z nowym kodem. Zobacz ten artykuł na temat tworzenia kopii zapasowych baz danych MS SQL, jeśli nie masz pewności.

Funkcja QUOTENAME

Funkcja „NAZWA KWOTOWANIA” formatuje wybrane wyniki. Przed wyjaśnieniem dynamicznego obrotu warto przyjrzeć się szybkiemu przykładowi działania funkcji „NAZWA WYWAŻENIA”.

Spójrz na następujące zapytanie.

USE schooldb

SELECT QUOTENAME(city)+ ','
FROM student

Domyślnie funkcja „NAZWA KWOTOWANIA” otacza wybrane elementy nawiasami kwadratowymi. Wynik powyższego zapytania wygląda tak:

[identyfikator tabeli=36 /]

Przechowywanie nazw kolumn w zmiennej

Mimo że otoczyliśmy wartości kolumn w nawiasy kwadratowe, musimy określić wartości w operatorze przestawnym w następującym formacie:

„[Leeds],[Liverpool],[Londyn],[Manchester]”

Aby to zrobić, potrzebujemy zmiennej.

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''

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

PRINT @CityNames

W powyższym zapytaniu zadeklarowaliśmy zmienną „@CityNames” i zainicjalizowaliśmy ją pustym ciągiem. Następnie użyliśmy instrukcji SELECT, aby wybrać różne nazwy miast z kolumny miasto i zapisać je iteracyjnie w zmiennej „@CityNames”. W każdej iteracji do zmiennej „@CityNames” zostanie dodana odrębna wartość w kolumnie miasta wraz z przecinkiem.

Następnie wydrukowaliśmy wartość przechowywaną w tej zmiennej. Wynik powyższego zapytania będzie wyglądał tak:

„[Leeds],[Liverpool],[Londyn],[Manchester]”

Jeśli spojrzysz na dane wyjściowe, po ostatniej wartości znajduje się przecinek. Nie potrzebujemy tego.

Usuwanie końcowego przecinka

Aby usunąć końcowy przecinek, użyjemy funkcji LEFT, która jako pierwszy argument przyjmuje ciąg znaków. Drugim argumentem jest liczba znaków, które mają zostać zwrócone z tego łańcucha, zaczynając od pierwszego znaku. Spójrz na następujące zapytanie:

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

Tutaj zwróć uwagę na ten wiersz skryptu:

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

W tej linii skryptu użyliśmy funkcji LEFT, aby pobrać wszystkie znaki po lewej stronie wartości przechowywanej w zmiennej „@CityNames”, zaczynając od pierwszego elementu. W drugim argumencie użyliśmy funkcji LEN do obliczenia liczby elementów wartości przechowywanych w funkcji „@CityNames” i na koniec odjęliśmy od niej 1. Spowoduje to usunięcie końcowego przecinka z ciągu. Wynik będzie wyglądał tak:

[Leeds],[Liverpool],[Londyn],[Manchester]

Konwertowanie zapytania SQL na ciąg

Teraz, miejmy nadzieję, możemy użyć zmiennej „@CityNames” w naszym operatorze przestawnym w ten sposób:

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

Nie możemy jednak użyć zmiennej wewnątrz naszego operatora przestawnego. Alternatywnym podejściem jest przekonwertowanie naszego kompletnego zapytania SQL na łańcuch. Wewnątrz tego ciągu zahaczymy naszą zmienną „@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

Tutaj zadeklarowaliśmy zmienną „@Query” i zapisaliśmy w niej nasze zapytanie SQL. Wewnątrz operatora przestawnego połączyliśmy wartość przechowywaną w zmiennej „@CityNames”. Aby zobaczyć, jak wygląda wykonane zapytanie, wydrukowaliśmy wartość zmiennej „@Query”. Wynikowe zapytanie będzie wyglądać tak na wyjściu:

SELECT * FROM

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

To jest dokładnie typ zapytania, które chcemy wykonać. Jest to jednak w formacie String. Ostatnim krokiem jest wykonanie tego zapytania SQL zapisanego jako ciąg tekstowy. W tym celu użyjemy Dynamic SQL.

Wykonywanie dynamicznego SQL

Używamy wbudowanej procedury „sp_executesql” do wykonywania dynamicznego SQL. Użyjemy tej procedury składowanej do wykonania zapytania przechowywanego w zmiennej @Query. Nasze ostatnie zapytanie, które tworzy dynamiczną tabelę przestawną, wygląda tak:

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 wykonaniu powyższego zapytania powinieneś zobaczyć następujący wynik:

[identyfikator tabeli=37 /]

Jednak tym razem nie określiliśmy ręcznie wartości nagłówków tabeli przestawnej. Zamiast tego nagłówki zostały obliczone dynamicznie, co daje dynamiczną tabelę przestawną.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać ostatni dzień miesiąca w T-SQL?

  2. Zrozumienie transakcji w SQL

  3. Szybkie znajdowanie odrębnych wartości

  4. Jak wygenerować dane testowe DB

  5. Poprawka błędu 2008 R2, która łamie RCSI