Jednoduchá SQL hádanka

Tomáš Herceg       29.07.2009       SQL, Databáze       11560 zobrazení

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:

Výsledek

Svoje řešení zasílejte na e-mailovou adresu string.Format(“{0}@{1}.{2}”, “herceg”, “vbnet”, “cz”).

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Diskuse: Jednoduchá SQL hádanka

select 
	tmp.[CategoryId], 
	tmp.Number 
from
	(select 
		[CategoryId], 
		[Number], 
		dense_Rank() over (Partition BY [CategoryId] order by [Number] ASC) as DRank
	from @t) tmp
where tmp.DRank < 5

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Sice půl roku po termínu, ale správně.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Jednoduchá SQL hádanka

Řešení je třeba v jedné knížce o T-SQL, ale nechci luštitelům kazit radost, tak neprozradím ve které ;-)

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback