Comment puis-je sélectionner dans la liste de valeurs dans SQL Server

220

J'ai un problème très simple que je ne peux pas résoudre. Je dois faire quelque chose comme ça:

select distinct * from (1, 1, 1, 2, 5, 1, 6).

Tout le monde peut aider ??

Éditer

Les données proviennent d'un fichier texte de l'un de nos clients. Il est totalement non formaté (c'est une seule et très longue ligne de texte), mais il peut être possible de le faire dans Excel. Mais ce n'est pas pratique pour moi, car je devrai utiliser ces valeurs dans ma requête SQL. Ce n'est pas pratique de le faire chaque fois que j'ai besoin d'exécuter une requête.

Eedoh
la source
voulez-vous sélectionner parmi plusieurs tables ou sélectionner parmi une seule table mais avec des valeurs spécifiques à sélectionner? quelque chose comme un identifiant spécifique seul
Anirudh Goel
Pas ce que vous demandez, mais vous pouvez le faire dans une autre langue. Par exemple, dans PowerShell, vous pouvez faire $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniquepour obtenir les valeurs distinctes dans un tableau $d. Facile à étendre à un outil de fichier à fichier.
Jeppe Stig Nielsen
Est-ce important pour obtenir une liste distincte de ces valeurs ou pour obtenir cette liste de valeurs dans SQL? Comme le dit @JeppeStigNielsen, il existe d'autres façons d'obtenir des valeurs distinctes à partir d'une liste de textes qui n'implique pas SQL. Je suis venu ici pour chercher comment obtenir une liste de valeurs dans un script SQL qui référence d'autres tables.
Rikki

Réponses:

82

Le moyen le plus simple d'obtenir les valeurs distinctes d'une longue liste de texte délimité par des virgules serait d'utiliser une recherche de remplacement par UNION pour obtenir les valeurs distinctes.

SELECT 1
UNION SELECT 1
UNION SELECT 1
UNION SELECT 2
UNION SELECT 5
UNION SELECT 1
UNION SELECT 6

Appliqué à votre longue ligne de texte délimité par des virgules

  • Trouvez et remplacez chaque virgule par UNION SELECT
  • Ajoutez un SELECTdevant la déclaration

Vous devriez maintenant avoir une requête de travail

Lieven Keersmaekers
la source
3
non, non, j'ai une liste de plusieurs centaines de valeurs, manuellement ce serait de la torture
Eedoh
d'où vient cette liste? Il pourrait être beaucoup plus facile de simplement copier / coller cette liste dans Excel et d'extraire les valeurs distinctes à l'aide d'un simple tableau croisé.
Lieven Keersmaekers
btw, trouver et remplacer peut également vous prendre beaucoup de temps. Remplacez chaque virgule par union select , ajoutez un select devant et vous devriez avoir une requête de travail cfr l'union que j'ai montrée.
Lieven Keersmaekers
1
ce truc avec le remplacement des virgules par certains syndicats fonctionne comme un charme Merci beaucoup :)
Eedoh
5
Pour des raisons de performances, je recommanderais Union-All, puis Group-By ou utilisez Distinct dans votre sélection externe.
MikeTeeVee
429

Disponible uniquement sur SQL Server 2008 et plus est constructeur de lignes sous cette forme:
vous pouvez utiliser

SELECT DISTINCT * FROM (VALUES (1), (1), (1), (2), (5), (1), (6)) AS X(a)

Beaucoup ont écrit, parmi eux:

après-midi.
la source
67
Note: Xest un alias pour le nom de la table et un aalias pour le nom de la colonne;).
shA.t
11
C'est la réponse la plus correcte par rapport à celle actuellement sélectionnée
TabsNotSpaces
1
C'est le moyen le plus générique, j'ai été gâté par unnest (ARRAY []) pgsqlet maintenant je frappe la tête pour que FROM accepte les valeurs mineures en tant qu'enregistrements de ligne dans sqlserver, et le voici. Content de le savoir.
Ben
1
Meilleure réponse grâce à l'alias de colonne et de table
Alfredo A.
81

En général :

SELECT 
  DISTINCT 
      FieldName1, FieldName2, ..., FieldNameN
FROM
  (
    Values
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN )
  ) AS TempTableName ( FieldName1, FieldName2, ..., FieldNameN )

Dans ton cas :

Select 
  distinct
  TempTableName.Field1 
From 
  (
  VALUES
    (1), 
    (1), 
    (1), 
    (2), 
    (5), 
    (1), 
    (6)
  ) AS TempTableName (Field1)
Ardalan Shahgholi
la source
1
Je sais que "select *" est considéré comme une mauvaise forme, mais y a-t-il une raison de ne pas utiliser select * dans ce cas? Parce que cette duplication de FieldName1, FieldName2, ..., FieldNameN est grotesque.
Pxtl
@Pxtl Il n'y a aucune raison de ne pas utiliser "Select *". J'ai réécrit les noms de ces champs pour être plus clair. De plus, vous n'avez peut-être pas besoin du mot-clé "Distinct".
Ardalan Shahgholi
43

Avez-vous essayé d'utiliser la syntaxe suivante?

select * from (values (1), (2), (3), (4), (5)) numbers(number)
Robba
la source
5
un utilisateur anonyme a suggéré de modifier le code pour:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612
19

Si vous ne souhaitez sélectionner que certaines valeurs dans une seule table, vous pouvez essayer ceci

select distinct(*) from table_name where table_field in (1,1,2,3,4,5)

par exemple:

select first_name,phone_number from telephone_list where district id in (1,2,5,7,8,9)

si vous souhaitez sélectionner parmi plusieurs tables, vous devez opter pour UNION .

Si vous souhaitez simplement sélectionner les valeurs 1, 1, 1, 2, 5, 1, 6, vous devez le faire

select 1 
union select 1 
union select 1 
union select 2 
union select 5 
union select 1 
union select 6
Anirudh Goel
la source
1
Je n'ai pas besoin de sélectionner dans une table, mais dans cette liste de valeurs (entre parenthèses). C'est le principal problème (sélection dans un tableau de valeurs séparées par des virgules, pas dans une table)
Eedoh
ce cas, comme nous avons la table DUAL dans Oracle, vous pouvez utiliser la même chose. Mais puisqu'il n'y a pas de DUAL, vous devrez suivre la voie syndicale. Vous pouvez essayer une autre méthode, comme vous l'avez mentionné, vous avez un tableau de valeurs séparées par des virgules, pourquoi ne pas les insérer dans une table, puis utiliser une requête de sélection sql soignée, au lieu d'utiliser autant d'unions sql.
Anirudh Goel,
15

PostgreSQL vous propose 2 façons de procéder:

SELECT DISTINCT * FROM (VALUES('a'),('b'),('a'),('v')) AS tbl(col1)

ou

SELECT DISTINCT * FROM (select unnest(array['a','b', 'a','v'])) AS tbl(col1)

en utilisant l'approche tableau, vous pouvez également faire quelque chose comme ceci:

SELECT DISTINCT * FROM (select unnest(string_to_array('a;b;c;d;e;f;a;b;d', ';'))) AS tbl(col1)
Arek
la source
11
Bien que la question spécifie MSSQL ...:)
halfer
@halfer La première réponse donnée ici a fonctionné pour moi, en utilisant MSSQL 2016 tandis que les autres réponses ne l'ont pas fait. 7 ans plus tard
dustytrash
9

Cela fonctionne sur SQL Server 2005 et s'il y a un nombre maximal:

SELECT * 
FROM
  (SELECT ROW_NUMBER() OVER(ORDER BY a.id) NUMBER
  FROM syscomments a
  CROSS JOIN syscomments b) c
WHERE c.NUMBER IN (1,4,6,7,9)
LukLed
la source
2
+1 net mais limité à la quantité de lignes dans les syscomments croisés avec lui-même. Dans mon cas au 294849. (et vous avez oublié distinct.)
Lieven Keersmaekers
Vous pouvez croiser la jointure une fois de plus, mais remplacer les virgules est une solution beaucoup plus rapide.
LukLed
Oui, cette façon est également bonne, mais je préfère la solution de Lieven, pour des raisons de simplicité.
Eedoh
3

Je sais que c'est un fil assez ancien, mais je cherchais quelque chose de similaire et j'ai trouvé ça.

Étant donné que vous disposiez d'une chaîne séparée par des virgules, vous pouvez utiliser string_split

select distinct value from string_split('1, 1, 1, 2, 5, 1, 6',',')

Cela devrait revenir

1
2
5
6

Le fractionnement de chaîne prend deux paramètres, l'entrée de chaîne et le caractère séparateur.

vous pouvez ajouter une instruction where facultative en utilisant valuecomme nom de colonne

select distinct value from string_split('1, 1, 1, 2, 5, 1, 6',',')
where value > 1

produit

2
5
6
NapkinBob
la source
Cela semble nécessiter MSSQL 2016 ou version ultérieure: docs.microsoft.com/en-us/sql/t-sql/functions/…
Jonathan
1
@Sam Oui, il s'agit de SQL Server, selon les balises de la question d'origine
NapkinBob
1
@Jonathan Oui, étant donné l'âge de la question, cela n'aurait pas aidé l'affiche originale, mais j'ai pensé que quelqu'un pourrait tomber dessus, comme je l'ai fait, et le trouver utile.
NapkinBob
2

Si vous avez besoin d'un tableau, séparez les colonnes du tableau par une virgule:

SELECT * FROM (VALUES('WOMENS'),('MENS'),('CHILDRENS')) as X([Attribute])
,(VALUES(742),(318)) AS z([StoreID])
gilgarola
la source
0

Vous pouvez également utiliser une requête comme celle-ci:

SELECT DISTINCT
    LTRIM(m.n.value('.[1]','varchar(8000)')) as columnName
FROM 
    (SELECT CAST('<XMLRoot><RowData>' + REPLACE(t.val,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
     FROM (SELECT '1, 1, 1, 2, 5, 1, 6') AS t(val)
    ) dt
  CROSS APPLY 
    x.nodes('/XMLRoot/RowData') m(n);
shA.t
la source
0

Sélectionnez l'ID utilisateur dans la liste des ID utilisateur:

SELECT * FROM my_table WHERE user_id IN (1,3,5,7,9,4);
Biplob Das
la source
-2

Une technique qui a fonctionné pour moi consiste à interroger une table dont vous savez qu'elle contient une grande quantité d'enregistrements, y compris uniquement le champ Row_Number dans votre résultat

Select Top 10000 Row_Number() OVER (Order by fieldintable) As 'recnum' From largetable

renverra un jeu de résultats de 10000 enregistrements de 1 à 10000, utilisez-le dans une autre requête pour vous donner les résultats souhaités

Jwalter
la source
-4

Utilisez la Infonction SQL

Quelque chose comme ça:

SELECT * FROM mytable WHERE:
"VALUE" In (1,2,3,7,90,500)

Fonctionne un régal dans ArcGIS

user3059384
la source
1
Ce SELECT génère une erreur de syntaxe avec SQL Server.
JohnH