Wie kann ich aus einer Werteliste in SQL Server auswählen?

216

Ich habe ein sehr einfaches Problem, das ich nicht lösen kann. Ich muss so etwas tun:

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

Jeder kann helfen?

Bearbeiten

Die Daten stammen als Textdatei von einem unserer Kunden. Es ist völlig unformatiert (es ist eine einzelne, sehr lange Textzeile), aber möglicherweise ist dies in Excel möglich. Für mich ist dies jedoch nicht praktikabel, da ich diese Werte in meiner SQL-Abfrage verwenden muss. Es ist nicht bequem, dies jedes Mal zu tun, wenn ich eine Abfrage ausführen muss.

Eedoh
quelle
Möchten Sie aus mehreren Tabellen oder aus einer einzelnen Tabelle auswählen, aber bestimmte Werte auswählen? etwas wie bestimmte IDs allein
Anirudh Goel
Nicht was Sie fragen, aber Sie können es in einer anderen Sprache tun. In PowerShell können Sie beispielsweise $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniquedie unterschiedlichen Werte in einem Array abrufen $d. Einfache Erweiterung auf ein Datei-zu-Datei-Tool.
Jeppe Stig Nielsen
Ist es hier wichtig, eine eindeutige Liste dieser Werte zu erhalten oder diese Werteliste in SQL zu übernehmen? Wie @JeppeStigNielsen sagt, gibt es andere Möglichkeiten, eindeutige Werte aus einer Textliste abzurufen, die kein SQL enthält. Ich bin hierher gekommen, um nach einer Liste von Werten in einem SQL-Skript zu suchen, das auf andere Tabellen verweist.
Rikki

Antworten:

81

Der einfachste Weg, um die unterschiedlichen Werte einer langen Liste von durch Kommas getrennten Texten zu erhalten, besteht darin, einen Ersatz durch UNION zu finden, um die unterschiedlichen Werte zu erhalten.

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

Wird auf Ihre lange, durch Kommas getrennte Textzeile angewendet

  • Suchen und ersetzen Sie jedes Komma durch UNION SELECT
  • Fügen Sie SELECTvor der Anweisung ein ein

Sie sollten jetzt eine funktionierende Abfrage haben

Lieven Keersmaekers
quelle
3
nein, nein, ich habe eine Liste von mehreren hundert Werten, manuell wäre es Folter
Eedoh
Woher kommt diese Liste? Es könnte viel einfacher sein, diese Liste einfach in Excel zu kopieren / einzufügen und die unterschiedlichen Werte dort mit einer einfachen Kreuztabelle zu extrahieren.
Lieven Keersmaekers
Übrigens kann das Suchen und Ersetzen auch einen langen Weg dauern. Ersetzen Sie jedes Komma durch Union Select , fügen Sie ein Select vor und Sie sollten eine funktionierende Abfrage für die Union haben, die ich angezeigt habe.
Lieven Keersmaekers
1
Dieses Zeug mit dem Ersetzen von Kommas durch ausgewählte Vereinigung funktioniert wie ein Zauber. Vielen Dank :)
Eedoh
5
Aus Leistungsgründen würde ich Union-All und dann Group-By empfehlen oder Distinct in Ihrer äußeren Auswahl verwenden.
MikeTeeVee
427

Nur unter SQL Server 2008 und höher verfügbar ist der Zeilenkonstruktor in folgender Form:
Sie können ihn verwenden

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

Viele schrieben darüber, darunter:

Uhr.
quelle
66
Randnotiz: Xist Alias ​​für Tabellenname und aAlias ​​für Spaltenname;).
shA.t
11
Dies ist die korrektere Antwort im Vergleich zu der aktuell ausgewählten
TabsNotSpaces
1
Dies ist der allgemeinste Weg, ich wurde von unnest (ARRAY []) verwöhnt pgsqlund schlug jetzt mit dem Kopf, damit FROM kleinere Werte als Zeilendatensätze akzeptiert sqlserver, und hier ist es. Schön zu wissen.
Ben
1
Bessere Antwort aufgrund des Spalten- und Tabellenalias
Alfredo A.
79

Allgemein :

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 )

In deinem Fall :

Select 
  distinct
  TempTableName.Field1 
From 
  (
  VALUES
    (1), 
    (1), 
    (1), 
    (2), 
    (5), 
    (1), 
    (6)
  ) AS TempTableName (Field1)
Ardalan Shahgholi
quelle
Ich weiß, dass "select *" als schlechte Form angesehen wird, aber gibt es in diesem Fall einen Grund, select * nicht zu verwenden? Da diese Duplizierung von FieldName1, FieldName2, ..., FieldNameN grotesk ist.
Pxtl
43

Haben Sie versucht, die folgende Syntax zu verwenden?

select * from (values (1), (2), (3), (4), (5)) numbers(number)
Robba
quelle
5
Ein anonymer Benutzer schlug vor, den Code zu bearbeiten, um:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612
19

Wenn Sie nur bestimmte Werte aus einer einzelnen Tabelle auswählen möchten, können Sie dies versuchen

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

z.B:

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

Wenn Sie aus mehreren Tabellen auswählen möchten, müssen Sie sich für entscheiden UNION .

Wenn Sie nur die Werte 1, 1, 1, 2, 5, 1, 6 auswählen möchten, müssen Sie dies tun

select 1 
union select 1 
union select 1 
union select 2 
union select 5 
union select 1 
union select 6
Anirudh Goel
quelle
1
Ich muss nicht aus einer Tabelle auswählen, sondern aus dieser Werteliste (in Klammern). Das ist das Hauptproblem (Auswahl aus einem durch Kommas getrennten Array von Werten, nicht aus einer Tabelle)
Eedoh
In diesem Fall können Sie, wie wir die DUAL-Tabelle in Oracle haben, dieselbe verwenden. Aber da es kein DUAL gibt, müssen Sie den gewerkschaftlichen Weg gehen. Sie können eine andere Methode ausprobieren, da Sie erwähnt haben, dass Sie ein durch Kommas getrenntes Array von Werten haben. Warum fügen Sie diese nicht in eine Tabelle ein und verwenden dann eine saubere SQL-Auswahlabfrage, anstatt so viele SQL-Vereinigungen zu verwenden.
Anirudh Goel
14

PostgreSQL bietet Ihnen zwei Möglichkeiten, dies zu tun:

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

oder

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

Mit dem Array-Ansatz können Sie auch Folgendes tun:

SELECT DISTINCT * FROM (select unnest(string_to_array('a;b;c;d;e;f;a;b;d', ';'))) AS tbl(col1)
Arek
quelle
11
Obwohl die Frage MSSQL spezifiziert ...:)
halfer
@halfer Die erste Antwort hier hat bei mir mit MSSQL 2016 funktioniert, während die anderen Antworten dies nicht taten. 7 Jahre später
Dustytrash
9

Dies funktioniert unter SQL Server 2005 und wenn es eine maximale Anzahl gibt:

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
quelle
2
+1 ordentlich, aber es ist auf die Anzahl der Zeilen in Syscomments beschränkt, die mit sich selbst gekreuzt sind. In meinem Fall bis 294849. (und Sie haben deutlich vergessen.)
Lieven Keersmaekers
Sie können die Verknüpfung erneut kreuzen, aber das Ersetzen von Kommas ist eine viel schnellere Lösung.
LukLed
Ja, dieser Weg ist auch gut, aber ich bevorzuge Lievens Lösung wegen der Einfachheit.
Eedoh
3

Ich weiß, dass dies ein ziemlich alter Thread ist, aber ich habe nach etwas Ähnlichem gesucht und mir das ausgedacht.

Vorausgesetzt, Sie hatten eine durch Kommas getrennte Zeichenfolge, können Sie diese verwenden string_split

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

Dies sollte zurückkehren

1
2
5
6

Die Zeichenfolgenaufteilung verwendet zwei Parameter, die Zeichenfolgeneingabe und das Trennzeichen.

Sie können eine optionale where-Anweisung hinzufügen, die valueals Spaltenname verwendet wird

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

produziert

2
5
6
ServietteBob
quelle
Dies scheint MSSQL 2016 oder höher zu erfordern: docs.microsoft.com/en-us/sql/t-sql/functions/…
Jonathan
1
@ Sam Ja, dies ist SQL Server, gemäß den Tags der ursprünglichen Frage
NapkinBob
1
@ Jonathan Ja, angesichts des Alters der Frage hätte es dem Originalplakat nicht geholfen, aber ich dachte, jemand könnte wie ich darauf stoßen und es hilfreich finden.
NapkinBob
2

Wenn Sie ein Array benötigen, trennen Sie die Array-Spalten durch ein Komma:

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

Eine andere Möglichkeit, die Sie verwenden können, ist eine Abfrage wie die folgende:

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.
quelle
0

Wählen Sie die Benutzer-ID aus der Liste der Benutzer-ID aus:

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

Eine Technik, die für mich funktioniert hat, besteht darin, eine Tabelle abzufragen, von der Sie wissen, dass sie eine große Anzahl von Datensätzen enthält, einschließlich nur des Felds Row_Number in Ihrem Ergebnis

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

Gibt eine Ergebnismenge von 10000 Datensätzen von 1 bis 10000 zurück. Verwenden Sie diese in einer anderen Abfrage, um die gewünschten Ergebnisse zu erhalten

Jwalter
quelle
-4

Verwenden Sie die SQL- InFunktion

Etwas wie das:

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

Funktioniert in ArcGIS

user3059384
quelle
1
Dieses SELECT generiert einen Syntaxfehler mit SQL Server.
JohnH