O víkendu jsem narychlo musel dělat jeden projekt a během něj jsem narazil na poměrně zajímavý problém. Máte tabulku se dvěma sloupci - Skupina a Datum. V každé skupině je několik datumů, takže tabulka má třeba 100 řádků, je v ní 10 různých skupin a v každé skupině je několik různých dat. Potřeboval jsem v databázi vybrat z každé skupiny třeba 5 nejnižších datumů a ideálně to celé chroupnout do 1 selectu, abych to nevybíral pro každou skupinu zvlášť (skupin jsou stovky, bylo by to pomalé). Otázkou je, jak tedy v MS SQL Serveru vybrat prvních n záznamů z každé skupiny (podle data) tak, abych pro každou skupinu nedělal separátní select. Abych to trochu zjednodušil, ten select nemusí být jeden, ale musí jich být konstantně mnoho - počet selectů nesmí záviset na počtu skupin ani na velikosti n (kolik záznamů z každé skupiny chceme).
Protože o víkendu, kdy jsem měl naspěch, mě inteligentní řešení na úrovni SQL nenapadlo, udělal jsem to na klientovi. Dnes ráno jsem si ale vzpomněl na jedno klíčové slovo v SQL, o kterém jsem věděl, ale vůbec jsem si neuvědomil, že bych ho měl použít.
Můžete použít tato testovací data (místo datumu jsem tam dal čísla, to je jedno, ono to vyjde nastejno):
-- testovací data
DECLARE @t TABLE ([CategoryId] INT, [Number] INT)
INSERT INTO @t VALUES (1, 1)
INSERT INTO @t VALUES (1, 4)
INSERT INTO @t VALUES (1, 7)
INSERT INTO @t VALUES (1, 15)
INSERT INTO @t VALUES (1, 26)
INSERT INTO @t VALUES (1, 27)
INSERT INTO @t VALUES (1, 48)
INSERT INTO @t VALUES (2, 1)
INSERT INTO @t VALUES (2, 5)
INSERT INTO @t VALUES (2, 9)
INSERT INTO @t VALUES (2, 10)
INSERT INTO @t VALUES (2, 15)
INSERT INTO @t VALUES (3, 1)
INSERT INTO @t VALUES (3, 2)
INSERT INTO @t VALUES (3, 3)
INSERT INTO @t VALUES (4, 1)
INSERT INTO @t VALUES (4, 4)
INSERT INTO @t VALUES (4, 8)
INSERT INTO @t VALUES (4, 13)
INSERT INTO @t VALUES (4, 20)
INSERT INTO @t VALUES (4, 95)
Z každé skupiny CategoryId chci vybrat 4 nejnižší hodnoty Number. Pokud je ve skupině záznamů méně, pochopitelně vybíráme celou skupinu. Výsledek by měl vypadat takto:
Svoje řešení zasílejte na e-mailovou adresu string.Format(“{0}@{1}.{2}”, “herceg”, “vbnet”, “cz”).