Як я можу вибрати зі списку значень у SQL Server


217

У мене дуже проста проблема, яку я не можу вирішити. Мені потрібно зробити щось подібне:

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

Хто-небудь може допомогти ??

Редагувати

Дані надходять у вигляді текстового файлу одного з наших клієнтів. Це абсолютно неформатоване (це єдиний, дуже довгий рядок тексту), але це можливо зробити в Excel. Але це для мене не практично, тому що мені потрібно буде використовувати ці значення у своєму запиті sql. Це не зручно робити це кожен раз, коли мені потрібно запустити запит.


ви хочете вибрати з декількох таблиць або вибрати з однієї таблиці, але маєте певні значення для вибору? щось подібне до конкретних ідентифікаторів
Anirudh Goel

Не те, що ви просите, але ви можете це зробити іншою мовою. Наприклад, у PowerShell, ви можете зробити, $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniqueщоб отримати різні значення в масиві $d. Легко поширюється на інструмент «файл у файл».
Джеппе Стіг Нільсен

Тут важливо отримати чіткий список цих значень або передати цей список значень у SQL? Як говорить @JeppeStigNielsen, існують і інші способи отримання чітких значень із текстового списку, який не включає SQL. Я прийшов сюди шукати, як отримати список значень у сценарій SQL, який посилається на інші таблиці.
Рікі

Відповіді:


81

Найпростішим способом отримати виразні значення з довгого списку з комою, обмеженим текстом , буде використання значного заміни на UNION, щоб отримати чіткі значення.

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

Застосовується до вашого довгого рядка з обмеженим комою текстом

  • Знайдіть і замініть кожну кому на UNION SELECT
  • Додайте SELECTперед заявою

Тепер у вас повинен бути робочий запит


3
ні, ні, у мене є список декількох сотень значень, вручну це було б катуванням
Eedoh

звідки цей список? Можливо, буде простіше просто скопіювати / вставити цей список в Excel і витягнути там різні значення за допомогою простого перехресного вкладки.
Лівен Кірсмейкерс

btw, пошук і заміна також може зайняти вас довгим шляхом. Замініть кожну кому на об'єкт select , додайте виділення попереду, і у вас повинен бути робочий запит cfr об'єднання, яке я показав.
Лівен Кірсмейкерс

1
цей матеріал із заміною коми на
вибраному

5
З міркувань продуктивності я рекомендую Union-All, потім Group-By або використовувати Distinct у своєму зовнішньому виборі.
MikeTeeVee

428

Доступний лише на SQL Server 2008 і вище, конструктор рядків у такій формі:
Ви можете використовувати

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

Багато хто писав про них, серед них:


66
Побічна примітка: Xпсевдонім для назви таблиці та aпсевдонім для імені стовпця;).
shA.t

11
Це більш правильна відповідь у порівнянні з обраною на даний момент
TabsNotSpaces

1
Це найзагальніший спосіб, мене зіпсував unnest (ARRAY []) в pgsqlі зараз стукав головою, щоб ВІД прийняти незначні значення як записи рядків sqlserver, і ось це. Рада знати.
Бен

1
Краща відповідь через псевдонім стовпців та таблиць
Альфредо А.

79

В загальному :

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 )

У вашому випадку:

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

1
Я знаю, що "select *" вважається поганою формою, але чи є причина в цьому випадку не використовувати select *? Тому що це дублювання FieldName1, FieldName2, ..., FieldNameN є гротескним.
Pxtl

@Pxtl Немає причин не використовувати "Select *". Я переписав назви цих полів, щоб бути більш чіткими. Крім того, вам, можливо, не потрібне ключове слово "Розрізнення".
Ардалан Шахголі

43

Ви спробували використовувати наступний синтаксис?

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

5
анонімний користувач запропонував змінити код на:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612

19

Якщо ви хочете вибрати лише певні значення з однієї таблиці, ви можете спробувати це

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

наприклад:

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

якщо ви хочете вибрати з декількох таблиць, тоді вам потрібно йти UNION.

Якщо ви просто хочете вибрати значення 1, 1, 1, 2, 5, 1, 6, ви повинні зробити це

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

1
Мені не потрібно вибирати з таблиці, але з цього списку значень (у дужках). У цьому головна проблема (вибір із масиву значень, розділених комами, а не з таблиці)
Eedoh

у такому випадку, як у нас є таблиця DUAL в Oracle, ви можете використовувати ту саму. Але оскільки немає ДУАЛІ, то вам доведеться йти профспілковим шляхом. Ви можете спробувати інший метод, оскільки ви згадали, що у вас є масив значень, розділених комами, чому ви не вставите їх у таблицю і не використовуєте акуратний запит вибору sql, замість того, щоб використовувати стільки союзів sql.
Аніруд Гоель

14

PostgreSQL дає 2 способи зробити це:

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

або

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

використовуючи масив підходу, ви також можете зробити щось подібне:

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

11
Хоча в питанні все ж вказано MSSQL ...:)
половина

@halfer Перша відповідь, дана тут, працювала для мене, використовуючи MSSQL 2016, тоді як інші відповіді не відповіли. 7 років пізніше
пиловловлення

9

Це працює на SQL Server 2005, і якщо є максимальна кількість:

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 охайний, але він обмежений кількістю рядків у хрестоподібних системах, поєднаних із собою. У моєму випадку до 294849. (і ви забули різницю)
Lieven Keersmaekers

Ви можете перекреслити приєднання ще раз, але заміна коми - це набагато швидше рішення.
LukLed

Так, цей спосіб також хороший, але я віддаю перевагу рішенню Лівена через простоту.
Eedoh

3

Я знаю, що це досить стара тема, але я шукав щось подібне і придумав це.

З огляду на те, що у вас був рядок, розділений комою, ви можете використовувати string_split

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

Це має повернутися

1
2
5
6

Розбиття рядків займає два параметри, рядок введення та роздільник.

ви можете додати необов'язковий де оператор, використовуючи valueяк назву стовпця

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

виробляє

2
5
6

Здається, це вимагає MSSQL 2016 або пізнішої версії: docs.microsoft.com/en-us/sql/t-sql/functions/…
Джонатан

1
@Sam Так, це SQL Server, відповідно до тегів оригіналу питання
NapkinBob

1
@Jonathan Так, враховуючи вік питання, це не допомогло б оригінальному плакату, але я вважав, що хтось може наткнутися на нього, як і я, і вважаю це корисним.
NapkinBob

2

Якщо вам потрібен масив, розділіть стовпці масиву комою:

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

0

Ще один спосіб, який ви можете використовувати, - це такий запит:

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

Виберіть ідентифікатор користувача зі списку ідентифікатора користувача:

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

-2

Метод, який працював для мене, - це запитувати таблицю, за якою ви знаєте, що в ній є велика кількість записів, включаючи лише поле Row_Number у вашому результаті

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

поверне набір результатів з 10000 записів від 1 до 10000, використовуйте це в іншому запиті, щоб отримати бажані результати


-4

Використання SQL Inфункції

Щось на зразок цього:

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

Працює частуванням в ArcGIS


1
Цей SELECT генерує синтаксичну помилку з SQL Server.
JohnH
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.