Potřebuji dotazovat databázi SQL, abych našel všechny odlišné hodnoty jednoho sloupce a potřebuji libovolnou hodnotu z jiného sloupce. Zvažte například následující tabulku se dvěma sloupci, klíčem a hodnotou:
key value
=== =====
one test
one another
one value
two goes
two here
two also
three example
Chtěl bych získat zpět jednu ukázkovou řadu, zvolenou libovolně, z každého odlišného klíče, možná získat tyto tři řádky:
key value
=== =====
one test
two goes
three example
Jak mohu formulovat takový dotaz v SQL?
Nejjednodušší dotaz k zápisu je pro MySQL (s přísným nastavením ANSI). Využívá nestandardní konstrukci:
SELECT key, value
FROM tableX
GROUP BY key ;
V nedávné verzi (5.7 a 8.0+), kde jsou přísná nastavení a ONLY_FULL_GROUP_BY
Výchozí, můžete použít funkci ANY_VALUE()
přidanou v 5.7:
SELECT key, ANY_VALUE(value) AS value
FROM tableX
GROUP BY key ;
Pro ostatní DBMS, které mají funkce okna (jako Postgres, SQL-Server, Oracle, DB2), je můžete použít takto. Výhodou je, že ve výsledku můžete také vybrat další sloupce (kromě key
a value
):
SELECT key, value
FROM tableX
( SELECT key, value,
ROW_NUMBER() OVER (PARTITION BY key
ORDER BY whatever) --- ORDER BY NULL
AS rn --- for example
FROM tableX
) tmp
WHERE rn = 1 ;
Pro starší verze výše a pro všechny ostatní DBMS, obecný způsob, který funguje téměř všude. Jednou z nevýhod je, že nemůžete vybrat další sloupce s tímto přístupem. Další je to, že agregační funkce jako MIN()
a MAX()
nefungují s některými datovými typy v některých DBMS (jako bit, text, kuličky):
SELECT key, MIN(value) AS value
FROM tableX
GROUP BY key ;
PostgreSQL má speciální nestandardní operátor DISTINCT ON
, Který lze také použít. Volitelný ORDER BY
Je pro výběr, který řádek z každé skupiny by měl být vybrán:
SELECT DISTINCT ON (key) key, value
FROM tableX
-- ORDER BY key, <some_other_expressions> ;
Pro server MS-SQl:
;with FinalDataset as
(
select *,
row_number() over(partition by key order by value) as rownum
from YourOriginalTable
)
select
key,
value
from FinalDataset
where rownum = 1
Podobně byste mohli mít rownum = 2 pro vaši druhou sadu výsledků
Podobně jako přijatá odpověď, ale místo min () nebo max () můžete použít array_agg ()
SELECT key, (array_agg(value))[1] AS value
FROM tableX
GROUP BY key ;
Chcete-li vybrat největší nebo nejmenší z nich, můžete volitelně objednat hodnoty uvnitř pole:
SELECT key, (array_agg(value) ORDER BY value DESC)[1] AS value
FROM tableX
GROUP BY key ;
(zaškrtnuto v PostgreSQL)