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.


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


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:


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)

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)

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

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)

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)

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

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

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

0

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

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

-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


-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


1
Ten WYBÓR generuje błąd składniowy w SQL Server.
— JohnH
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.