web-dev-qa-db-fra.com

requête SQL distincte avec Row_Number

Je me bats avec le mot clé distinct dans sql. Je veux juste afficher tous les numéros de ligne de valeurs uniques (distinct) dans une colonne et j'ai donc essayé:

SELECT distinct id, ROW_NUMBER() OVER (ORDER BY  id) AS RowNum
                             FROM table
                             where fid = 64

cependant, le code ci-dessous me donne les valeurs distinct:

SELECT distinct id FROM table where fid = 64

mais quand essayé avec Row_Number.
alors cela ne fonctionne pas.

47
objectWithoutClass

Utilisez ceci:

SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS RowNum FROM
    (SELECT DISTINCT id FROM table WHERE fid = 64) Base

et mettre la "sortie" d'une requête comme "entrée" d'une autre.

Utilisation du CTE:

; WITH Base AS (
    SELECT DISTINCT id FROM table WHERE fid = 64
)

SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS RowNum FROM Base

Les deux requêtes doivent être équivalentes.

Techniquement, vous pourriez

SELECT DISTINCT id, ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS RowNum 
    FROM table
    WHERE fid = 64

mais si vous augmentez le nombre de champs DISTINCT, vous devez mettre tous ces champs dans le PARTITION BY, donc par exemple

SELECT DISTINCT id, description,
    ROW_NUMBER() OVER (PARTITION BY id, description ORDER BY id) AS RowNum 
    FROM table
    WHERE fid = 64

J'espère même que vous comprenez que vous allez à l'encontre des conventions de nommage standard ici, id devrait probablement être une clé primaire, donc unique par définition, si bien qu'un DISTINCT serait inutile, à moins que vous ne coupliez la requête avec quelque JOINs/UNION ALL...

44
xanatos

Cela peut être fait très simplement, vous étiez déjà assez proche

SELECT distinct id, DENSE_RANK() OVER (ORDER BY  id) AS RowNum
FROM table
WHERE fid = 64
85
t-clausen.dk

Cet article traite d'une relation intéressante entre ROW_NUMBER() et DENSE_RANK() (la fonction RANK() n'est pas traitée spécifiquement). Lorsque vous avez besoin d'une ROW_NUMBER() générée sur une instruction SELECT DISTINCT, Le ROW_NUMBER()) produira des valeurs distinctes avant ils sont supprimés par le mot clé DISTINCT . Par exemple. cette requête

SELECT DISTINCT
  v, 
  ROW_NUMBER() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number

... pourrait produire ce résultat (DISTINCT n'a aucun effet):

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| a |          2 |
| a |          3 |
| b |          4 |
| c |          5 |
| c |          6 |
| d |          7 |
| e |          8 |
+---+------------+

Considérant que cette requête:

SELECT DISTINCT
  v, 
  DENSE_RANK() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number

... produit ce que vous voulez probablement dans ce cas:

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| b |          2 |
| c |          3 |
| d |          4 |
| e |          5 |
+---+------------+

Notez que la clause ORDER BY De la fonction DENSE_RANK() aura besoin de toutes les autres colonnes de la clause SELECT DISTINCT Pour fonctionner correctement.

Les trois fonctions en comparaison

Utilisation de la syntaxe standard PostgreSQL/Sybase/SQL (clause WINDOW):

SELECT
  v,
  ROW_NUMBER() OVER (window) row_number,
  RANK()       OVER (window) rank,
  DENSE_RANK() OVER (window) dense_rank
FROM t
WINDOW window AS (ORDER BY v)
ORDER BY v

... tu auras:

+---+------------+------+------------+
| V | ROW_NUMBER | RANK | DENSE_RANK |
+---+------------+------+------------+
| a |          1 |    1 |          1 |
| a |          2 |    1 |          1 |
| a |          3 |    1 |          1 |
| b |          4 |    4 |          2 |
| c |          5 |    5 |          3 |
| c |          6 |    5 |          3 |
| d |          7 |    7 |          4 |
| e |          8 |    8 |          5 |
+---+------------+------+------------+
21
Lukas Eder

L'utilisation de DISTINCT provoque des problèmes lors de l'ajout de champs et peut également masquer des problèmes dans votre sélection. Utilisation GROUP BY comme une alternative comme celle-ci:

SELECT id
      ,ROW_NUMBER() OVER (ORDER BY  id) AS RowNum
  FROM table
 where fid = 64
 group by id

Ensuite, vous pouvez ajouter d'autres informations intéressantes à partir de votre sélection, comme ceci:

,count(*) as thecount

ou

,max(description) as description
3
Michael Potter

Que diriez-vous de quelque chose comme

;WITH DistinctVals AS (
        SELECT  distinct id 
        FROM    table 
        where   fid = 64
    )
SELECT  id,
        ROW_NUMBER() OVER (ORDER BY  id) AS RowNum
FROM    DistinctVals

SQL Fiddle DEMO

Tu pourrais aussi essayer

SELECT distinct id, DENSE_RANK() OVER (ORDER BY  id) AS RowNum
FROM @mytable
where fid = 64

SQL Fiddle DEMO

1
Adriaan Stander

Essaye ça

SELECT distinct id
FROM  (SELECT id, ROW_NUMBER() OVER (ORDER BY  id) AS RowNum
      FROM table
      WHERE fid = 64) t

Ou utilisez RANK() au lieu du numéro de ligne et sélectionnez les enregistrements DISTINCT rank

SELECT id
FROM  (SELECT id, ROW_NUMBER() OVER (PARTITION BY  id ORDER BY  id) AS RowNum
      FROM table
      WHERE fid = 64) t
WHERE t.RowNum=1

Cela renvoie également les identifiants distincts

0
Nithesh

Essaye ça:

;WITH CTE AS (
               SELECT DISTINCT id FROM table WHERE fid = 64
             )
SELECT id, ROW_NUMBER() OVER (ORDER BY  id) AS RowNum
  FROM cte
 WHERE fid = 64
0
hims056