it-swarm-eu.dev

Jak vybrat odlišný pro jeden sloupec a pro jiný sloupec?

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?

32
WilliamKF

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> ;
38
ypercubeᵀᴹ

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ů

3
JP Chauhan

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)

2
alexkovelsky