Jak mogę wybrać z listy wartości w SQL Server

217

Mam bardzo prosty problem, którego nie mogę rozwiązać. Muszę zrobić coś takiego:

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

Czy ktoś może pomóc?

Edytować

Dane pochodzą w postaci pliku tekstowego od jednego z naszych klientów. Jest całkowicie niesformatowany (jest to pojedyncza, bardzo długa linia tekstu), ale może to być możliwe w programie Excel. Ale to nie jest dla mnie praktyczne, ponieważ będę musiał użyć tych wartości w moim zapytaniu sql. Nie jest to wygodne za każdym razem, gdy muszę uruchomić zapytanie.

Eedoh
źródło
chcesz wybrać z wielu tabel lub wybrać jedną tabelę, ale mając określone wartości do wyboru? coś takiego jak sam konkretny identyfikator
Anirudh Goel
Nie to, o co prosisz, ale możesz to zrobić w innym języku. Na przykład w PowerShell można zrobić, $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniqueaby uzyskać różne wartości w tablicy $d. Łatwy do rozszerzenia na narzędzie do pliku.
Jeppe Stig Nielsen,
Czy ważna jest tutaj osobna lista tych wartości, czy też przeniesienie tej listy wartości do SQL? Jak mówi @JeppeStigNielsen, istnieją inne sposoby uzyskania odrębnych wartości z listy tekstowej, która nie obejmuje SQL. Przyszedłem tutaj, aby dowiedzieć się, jak uzyskać listę wartości w skrypcie SQL, który odwołuje się do innych tabel.
Rikki,

Odpowiedzi:

81

Najprostszym sposobem na uzyskanie odrębnych wartości długiej listy tekstu rozdzielanego przecinkami byłoby użycie funkcji find zamień na UNION, aby uzyskać różne wartości.

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

Stosowany do długiej linii tekstu rozdzielanego przecinkami

  • Znajdź i zamień każdy przecinek na UNION SELECT
  • Dodaj SELECTprzed wyciągiem

Powinieneś teraz mieć działające zapytanie

Lieven Keersmaekers
źródło
3
nie, nie, mam listę kilkuset wartości, ręcznie byłoby to tortury
Eedoh
skąd pochodzi ta lista? O wiele łatwiej jest po prostu skopiować / wkleić tę listę w programie Excel i wyodrębnić tam różne wartości za pomocą prostej tabeli przestawnej.
Lieven Keersmaekers
btw, znajdź i zamień może również zająć ci długą drogę. Zamień każdy przecinek na wybór unii , dodaj zaznaczenie z przodu, a powinieneś mieć działające zapytanie od unii, którą pokazałem.
Lieven Keersmaekers
1
te rzeczy z zastąpieniem przecinków wybranymi związkami działają jak urok Bardzo dziękuję :)
Eedoh
5
Ze względu na wydajność polecam Union-All, a następnie Group-By lub użyj Distinct w swoim zewnętrznym zaznaczeniu.
MikeTeeVee
428

Dostępny tylko w SQL Server 2008 i nowszych wersjach jest konstruktorem wierszy w następującej formie:
Możesz użyć

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

Wielu pisało o nich, wśród nich:

po południu.
źródło
66
Uwaga dodatkowa: Xto alias nazwy tabeli i aalias nazwy kolumny;).
shA.t
11
To jest bardziej poprawna odpowiedź w porównaniu do obecnie wybranej
TabsNotSpaces
1
Jest to najbardziej ogólny sposób, zostałem zepsuty przez unnest (ARRAY []) pgsqli teraz walę głową, aby FROM zaakceptował drobne wartości jako rekordy wiersza sqlserver, i oto jest. Chętnie to wiem.
Ben
1
Lepsza odpowiedź dzięki aliasowi kolumny i tabeli
Alfredo A.
79

Ogólnie :

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 )

W Twoim przypadku :

Select 
  distinct
  TempTableName.Field1 
From 
  (
  VALUES
    (1), 
    (1), 
    (1), 
    (2), 
    (5), 
    (1), 
    (6)
  ) AS TempTableName (Field1)
Ardalan Shahgholi
źródło
1
Wiem, że „select *” jest uważane za złą formę, ale czy jest jakiś powód, aby nie używać select * w tym przypadku? Ponieważ to powielanie FieldName1, FieldName2, ..., FieldNameN jest groteskowe.
Pxtl
@Pxtl Nie ma powodu, aby nie używać opcji „Wybierz *”. Przepisałem nazwy tych pól, aby były bardziej przejrzyste. Ponadto może nie potrzebujesz słowa kluczowego „Distinct”.
Ardalan Shahgholi
43

Czy próbowałeś użyć następującej składni?

select * from (values (1), (2), (3), (4), (5)) numbers(number)
Robba
źródło
5
anonimowy użytkownik zaproponował edycję kodu do:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612,
19

Jeśli chcesz wybrać tylko niektóre wartości z jednej tabeli, możesz spróbować

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

na przykład:

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

jeśli chcesz wybrać z wielu tabel, musisz przejść UNION.

Jeśli chcesz tylko wybrać wartości 1, 1, 1, 2, 5, 1, 6, musisz to zrobić

select 1 
union select 1 
union select 1 
union select 2 
union select 5 
union select 1 
union select 6
Anirudh Goel
źródło
1
Nie muszę wybierać z tabeli, ale z tej listy wartości (w nawiasach). To jest główny problem (wybór z tablicy wartości oddzielonych przecinkami, a nie z tabeli)
Eedoh
w takim przypadku, podobnie jak mamy tabelę DUAL w Oracle, możesz z niej korzystać. Ale ponieważ nie ma DUALU, będziesz musiał iść drogą związkową. Możesz wypróbować inną metodę, jak już wspomniałeś, masz rozdzieloną przecinkami tablicę wartości, dlaczego nie wstawisz ich do tabeli, a następnie użyjesz czystego zapytania select sql, zamiast używania tak wielu związków sql.
Anirudh Goel
14

PostgreSQL oferuje 2 sposoby:

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

lub

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

używając metody tablicowej możesz również zrobić coś takiego:

SELECT DISTINCT * FROM (select unnest(string_to_array('a;b;c;d;e;f;a;b;d', ';'))) AS tbl(col1)
Arek
źródło
11
Chociaż pytanie określa MSSQL ...:)
halfer
@halfer Pierwsza odpowiedź podana tutaj działała dla mnie, używając MSSQL 2016, podczas gdy inne odpowiedzi nie. 7 lat później
dustytrash,
9

Działa to na SQL Server 2005 i jeśli jest maksymalna liczba:

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
źródło
2
+1 schludne, ale jest ograniczone do liczby rzędów w połączonych ze sobą rzędach. W moim przypadku do 294849. (i zapomniałeś wyraźnie).
Lieven Keersmaekers
Możesz połączyć krzyżowo jeszcze raz, ale zastąpienie przecinków jest znacznie szybszym rozwiązaniem.
LukLed
Tak, ta droga też jest dobra, ale wolę rozwiązanie Lieven ze względu na prostotę.
Eedoh
3

Wiem, że to dość stary wątek, ale szukałem czegoś podobnego i wymyśliłem to.

Biorąc pod uwagę, że masz ciąg oddzielony przecinkami, możesz użyć string_split

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

To powinno wrócić

1
2
5
6

Podział łańcucha wymaga dwóch parametrów: wejściowego ciągu i znaku separatora.

możesz dodać opcjonalną instrukcję where, używając valuejako nazwy kolumny

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

produkuje

2
5
6
NapkinBob
źródło
Wydaje się, że wymaga to MSSQL 2016 lub nowszej: docs.microsoft.com/en-us/sql/t-sql/functions/...
Jonathan
1
@Sam Tak, to SQL Server, zgodnie z oryginalnymi tagami pytania
NapkinBob
1
@Jonathan Tak, biorąc pod uwagę wiek pytania, nie pomogłoby to oryginalnemu plakatowi, ale pomyślałem, że ktoś mógłby się na niego natknąć, tak jak ja, i uważam to za pomocne.
NapkinBob
2

Jeśli potrzebujesz tablicy, oddziel kolumny tablicy przecinkiem:

SELECT * FROM (VALUES('WOMENS'),('MENS'),('CHILDRENS')) as X([Attribute])
,(VALUES(742),(318)) AS z([StoreID])
Gilgarola
źródło
0

Innym sposobem na użycie jest zapytanie takie jak to:

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
źródło
0

Wybierz identyfikator użytkownika z listy identyfikatora użytkownika:

SELECT * FROM my_table WHERE user_id IN (1,3,5,7,9,4);
Biplob Das
źródło
-2

Techniką, która zadziałała dla mnie, jest zapytanie do tabeli, o której wiesz, że zawiera dużą liczbę rekordów, w tym tylko pole Row_Number w wyniku

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

zwróci zestaw wyników 10000 rekordów od 1 do 10000, użyj tego w innym zapytaniu, aby uzyskać pożądane wyniki

Jwalter
źródło
-4

Użyj SQL In funkcji

Coś takiego:

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

Działa przysmak w ArcGIS

użytkownik3059384
źródło
1
Ten WYBÓR generuje błąd składniowy w SQL Server.
JohnH