Come posso selezionare dall'elenco dei valori in SQL Server


220

Ho un problema molto semplice che non posso risolvere. Devo fare qualcosa del genere:

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

Qualcuno può aiutare ??

modificare

I dati provengono come file di testo da uno dei nostri clienti. È totalmente non formattato (è un'unica riga di testo molto lunga), ma potrebbe essere possibile farlo in Excel. Ma non è pratico per me, perché dovrò usare questi valori nella mia query sql. Non è conveniente farlo ogni volta che devo eseguire una query.


vuoi selezionare da più tabelle o selezionare da una singola tabella ma hai valori specifici da selezionare? qualcosa come un ID specifico è solo
Anirudh Goel,

Non quello che chiedi, ma puoi farlo in un'altra lingua. Ad esempio in PowerShell, è possibile fare $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniqueper ottenere i valori distinti in un array $d. Facile da estendere a uno strumento da file a file.
Jeppe Stig Nielsen,

La cosa importante qui è ottenere un elenco distinto di quei valori o ottenere tale elenco di valori in SQL? Come dice @JeppeStigNielsen, ci sono altri modi per ottenere valori distinti da un elenco di testo che non coinvolge SQL. Sono venuto qui alla ricerca di come ottenere un elenco di valori in uno script SQL che fa riferimento ad altre tabelle.
Rikki,

Risposte:


82

Il modo più semplice per ottenere i valori distinti di un lungo elenco di testo delimitato da virgole sarebbe quello di utilizzare un trova un rimpiazzo con UNION per ottenere i valori distinti.

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

Applicato alla tua lunga riga di testo delimitato da virgole

  • Trova e sostituisci ogni virgola con UNION SELECT
  • Aggiungi SELECTa davanti all'istruzione

Ora dovresti avere una query funzionante


3
no, no, ho un elenco di diverse centinaia di valori, manualmente sarebbe una tortura
Eedoh,

da dove viene quella lista? Potrebbe essere molto più semplice semplicemente copiare / incollare l'elenco in Excel ed estrarre i valori distinti lì utilizzando una semplice tabella a campi incrociati.
Lieven Keersmaekers,

tra l'altro, trovare e sostituire potrebbe anche richiedere molto tempo. Sostituisci ogni virgola con la selezione unione , aggiungi una selezione in primo piano e dovresti avere una query funzionante cfr l'unione che ho mostrato.
Lieven Keersmaekers,

1
questa roba con la sostituzione di virgole con unione selezionata funziona come un incantesimo Grazie mille :)
Eedoh

5
Per motivi di prestazioni, consiglierei Union-All, quindi Group-By o utilizzare Distinct nella selezione esterna.
MikeTeeVee,

429

Disponibile solo su SQL Server 2008 e versioni successive è il costruttore di righe in questo formato:
è possibile utilizzare

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

Molti hanno scritto, tra cui:


67
Nota a margine: Xè alias per il nome della tabella ed aè alias per il nome della colonna;).
shA.t

11
Questa è la risposta più corretta rispetto a quella attualmente selezionata
TabsNotSpaces

1
Questo è il modo più generico, sono stato viziato da inutili (ARRAY []) pgsqle ora sbatto la testa per fare in modo che FROM accetti i valori minori come record di riga sqlserver, ed eccolo qui. Felice di sapere
Ben

1
Migliore risposta grazie all'alias di colonne e tabelle
Alfredo A.

81

In generale :

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 )

Nel tuo caso :

Select 
  distinct
  TempTableName.Field1 
From 
  (
  VALUES
    (1), 
    (1), 
    (1), 
    (2), 
    (5), 
    (1), 
    (6)
  ) AS TempTableName (Field1)

1
So che "select *" è considerato in cattiva forma, ma c'è qualche motivo per non usare select * in questo caso? Perché quella duplicazione di FieldName1, FieldName2, ..., FieldNameN è grottesca.
Pxtl,

@Pxtl Non vi è alcun motivo per non utilizzare "Seleziona *". Ho riscritto i nomi di quei campi per essere più chiari. Inoltre, potresti non aver bisogno della parola chiave "Distinct".
Ardalan Shahgholi,

43

Hai provato a usare la sintassi seguente?

select * from (values (1), (2), (3), (4), (5)) numbers(number)

5
un utente anonimo ha suggerito di modificare il codice in:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612

19

Se vuoi selezionare solo determinati valori da una singola tabella puoi provare questo

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

per esempio:

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

se si desidera selezionare tra più tabelle, è necessario scegliere UNION.

Se vuoi solo selezionare i valori 1, 1, 1, 2, 5, 1, 6, devi farlo

select 1 
union select 1 
union select 1 
union select 2 
union select 5 
union select 1 
union select 6

1
Non ho bisogno di selezionare da una tabella, ma da questo elenco di valori (tra parentesi). Questo è il problema principale (selezionando da una matrice di valori separata da virgola, non da una tabella)
Eedoh,

quel caso, come abbiamo la tabella DUAL in Oracle, puoi farne uso. Ma dal momento che non esiste DUAL, dovrai seguire la strada del sindacato. Puoi provare un altro metodo, come hai detto che hai una matrice di valori separata da virgole, perché non inserirli in una tabella e quindi utilizzare una query di selezione sql ordinata, invece di usare così tanti sindacati sql.
Anirudh Goel,

15

PostgreSQL ti offre 2 modi per farlo:

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

o

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

usando l'approccio array puoi anche fare qualcosa del genere:

SELECT DISTINCT * FROM (select unnest(string_to_array('a;b;c;d;e;f;a;b;d', ';'))) AS tbl(col1)

11
Anche se la domanda specifica MSSQL ...:)
halfer

@halfer La prima risposta fornita qui ha funzionato per me, usando MSSQL 2016 mentre le altre risposte no. 7 anni dopo
dustytrash,

9

Funziona su SQL Server 2005 e se esiste un numero massimo:

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)

2
+1 pulito ma è limitato alla quantità di righe nei sistemi incrociate unite a se stesse. Nel mio caso al 294849. (e hai dimenticato distinto.)
Lieven Keersmaekers,

È possibile incrociare nuovamente il join, ma la sostituzione delle virgole è una soluzione molto più rapida.
LukLed

Sì, anche in questo modo va bene, ma preferisco la soluzione di Lieven, per semplicità.
Eedoh,

3

So che questo è un thread piuttosto vecchio, ma stavo cercando qualcosa di simile e mi è venuto in mente.

Dato che avevi una stringa separata da virgola, puoi usare string_split

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

Questo dovrebbe tornare

1
2
5
6

La suddivisione in stringhe accetta due parametri, l'input della stringa e il carattere separatore.

puoi aggiungere un'istruzione where facoltativa usando valuecome nome della colonna

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

produce

2
5
6

Questo sembra richiedere MSSQL 2016 o versioni
Jonathan

1
@Sam Sì, si tratta di SQL Server, per i tag della domanda originale
NapkinBob,

1
@Jonathan Sì, data l'età della domanda, non avrebbe aiutato il poster originale, ma ho pensato che qualcuno potesse inciampare su di esso, come ho fatto, e trovarlo utile.
NapkinBob,

2

Se è necessaria una matrice, separare le colonne della matrice con una virgola:

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

0

Un altro modo che puoi usare è una query come questa:

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);

0

Seleziona ID utente dall'elenco di ID utente:

SELECT * FROM my_table WHERE user_id IN (1,3,5,7,9,4);

-2

Una tecnica che ha funzionato per me è quella di interrogare una tabella che sai contiene una grande quantità di record, incluso solo il campo Row_Number nel tuo risultato

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

restituirà un set di risultati di 10000 record da 1 a 10000, utilizzarlo all'interno di un'altra query per ottenere i risultati desiderati


-4

Usa la Infunzione SQL

Qualcosa come questo:

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

Funziona a meraviglia in ArcGIS


1
Questo SELECT genera un errore di sintassi con SQL Server.
John
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.