• 20.8.2016
  • Ing. Jan Zedníček - Data Engineer & Controlling
  • 0

Jako Loop můžeme označit opakované volání části kódu s různými parametry a většinou je spojen s nějakou DML operací typu INSERT nebo UPDATE. Cyklus voláme po předem stanovený počet opakování a můžeme ho v SQL sestavit několika různými způsoby. Na příkladu s kalendářem si ukážeme všechny způsoby.

Jak na Generování kalendáře v SQL pomocí cyklu?

Dejme tomu, že bychom si chtěli vyrobit v databázi tabulku s kalendářem od 1.1.1980 do 31.12.2050. Kalendář se dá do databáze pochopitelně založit i elegantnějšími způsoby než použitím cyklu, berme to jako cvičení.

Založení prázdné tabulky s kalendářem jako příprava:

CREATE TABLE #Calendar(
   [Datum] [Date] PRIMARY KEY,
   [DenRoku]     AS (DATEPART(DAYOFYEAR,[Datum])),
   [DenTydne]    AS (DATEPART(WEEKDAY,[Datum])),
   [Mesic]       AS (DATENAME(MONTH,DATEADD(MONTH,DATEPART(MONTH,[Datum]),(0))-(1))),
   [Kvartal]     AS (CONCAT(DATEPART(QUARTER,[Datum]),'Q')),
   [Rok]         AS (DATEPART(YEAR,[Datum]))
);

Tempovou tabulku pro účely příkladu zakládáme s calculated fieldy abychom nemuseli opakovaně vkládat celý seznam polí, ale pouze [Datum]. Po založení tabulky tímto způsobem stačí vkládat jednotlivé datumy a zbytek polí se posléze automaticky dopočítá.

Způsob – GOTO metoda

Tento způsob není příliš doporučován, protože je pomalejší než ostatní. Spočívá v definici label (např. “SQL_CYKLUS_START:”) ke kterému se prostřednictvím příkazu GOTO v jednotlivých iteracích vracíme.

DECLARE @datum_plovouci AS SMALLDATETIME = '1980-01-01';
DECLARE
@datum_zarazka AS SMALLDATETIME = '2050-12-31';

SQL_CYKLUS_START:

   INSERT INTO #Calendar ([datum])
   VALUES(@datum_plovouci)
   SET @datum_plovouci = @datum_plovouci+1

IF @datum_plovouci < @datum_zarazka
GOTO SQL_CYKLUS;

SELECT * FROM #Calendar;

WHILE/BEGIN/END Cyklus

WHILE příkazem provádíme opakované volání kódu následujícího po while (většinou odděleného BEGIN/END) a to do doby dokud platí podmínka následující po WHILE

/*promažeme záznamy v naší tabulce a vložíme datumy jinám zpusobem*/

TRUNCATE TABLE #Calendar;

DECLARE @datum_plovouci AS SMALLDATETIME = '1980-01-01'
DECLARE @datum_zarazka AS SMALLDATETIME = '2050-12-31'

WHILE @datum_plovouci< @datum_zarazka
BEGIN
INSERT INTO
#Calendar ([datum])
  VALUES(@datum_plovouci)
SET @datum_plovouci=@datum_plovouci+1
END;

Rekurzivní CTE (Common table expression)

Rekurzivní CTE jsou zdaleka nejrychlejším způsobem jak dosáhnout výsledku:

/*promažeme záznamy v naší tabulce a vložíme datumy jinám zpusobem*/
TRUNCATE TABLE #Calendar;

DECLARE @datum_plovouci AS SMALLDATETIME = '1980-01-01';
DECLARE @datum_zarazka AS SMALLDATETIME = '2050-12-31'

;WITH [CTE_Date] ([Datum]) AS (
   SELECT @datum_plovouci AS DATUM
     UNION ALL
   SELECT [DATUM]+1 AS DATUM
   FROM [CTE_Date]
   WHERE [DATUM] + 1<@datum_zarazka
)
INSERT INTO #Calendar
SELECT * FROM [CTE_Date] OPTION (MAXRECURSION 32767);

Více se o rekurzivních dotazech můžete dozvěděl z webu Microsoftu

Rate this post

Ing. Jan Zedníček - Data Engineer & Controlling

Jmenuji se Honza Zedníček a působím jako freelancer. Pracoval jsem dříve také jako BI developer, finanční controller a analytik. Vše pro společnosti z oblasti IT, bankovnictví, consultingu a výroby. Po práci si rád zahraju tenis, volejbal, šachy, zajdu do posilovny a občas neúspěšně odpálím pár balónků v golfu 🏌️

Již cca 10 let zapisuji na tento web různé návody určené zejména odborné veřejnosti, studentům a zájemcům o informace z oblastí Business intelligence, korporátních financí a reportingu.

🔥 Přihlašte se do naší Excel facebook skupiny (2.4k+ členů), kde si pomáháme Excel CZ/SK diskuse »

Leave a Reply

Your email address will not be published. Required fields are marked *