Как я могу выбрать из списка значений в SQL Server


220

У меня очень простая проблема, которую я не могу решить. Мне нужно сделать что-то вроде этого:

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

Кто-нибудь может помочь ??

редактировать

Данные поступают в виде текстового файла от одного из наших клиентов. Он полностью не отформатирован (это одна очень длинная строка текста), но это возможно сделать в Excel. Но это не практично для меня, потому что мне нужно будет использовать эти значения в моем SQL-запросе. Это не удобно делать каждый раз, когда мне нужно выполнить запрос.


Вы хотите выбрать из нескольких таблиц или выбрать из одной таблицы, но выбрать конкретные значения? что-то вроде одного конкретного идентификатора
Анируд Гоэль

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

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

Ответы:


82

Простейший способ получить отличительные значения длинного списка текста, разделенного запятыми , состоит в том, чтобы найти замену с помощью 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 и извлечь из него отдельные значения с помощью простой кросс-таблицы.
Ливен Керсмакерс

Кстати, найти и заменить также может пройти долгий путь. Замените каждую запятую на союз выбора , добавьте выбор впереди, и у вас должен быть рабочий запрос для союза, который я показал.
Ливен Керсмакерс

1
этот материал с заменой запятых на select union работает как шарм Большое спасибо :)
Eedoh

5
Из соображений производительности я бы порекомендовал Union-All, затем Group-By или использовать Distinct в качестве внешнего выбора.
MikeTeeVee

429

Доступно только в SQL Server 2008 и более, это конструктор строк в этой форме:
вы можете использовать

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

Многие писали о среди них:


67
Примечание: Xэто псевдоним для имени таблицы и aпсевдоним для имени столбца;).
ShA.t

11
Это более правильный ответ по сравнению с выбранным в данный момент
TabsNotSpaces

1
Это наиболее общий способ, я был испорчен unnest (ARRAY []) в pgsqlи теперь стучит головой, чтобы заставить FROM принимать второстепенные значения в качестве записей строк sqlserver, и вот оно. Рад знать.
Бен

1
Лучший ответ благодаря псевдониму столбца и таблицы
Альфредо А.

81

В основном :

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 Нет причин не использовать «Выбрать *». Я переписал названия этих полей, чтобы они были более понятными. Кроме того, вам, возможно, не нужно ключевое слово "Distinct".
Ардалан Шахголи

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.
Анируд Гоэль

15

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

@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 аккуратно, но это ограничено количеством строк в syscomments, соединенных между собой. В моем случае до 294849. (а вы забыли внятно.)
Ливен Керсмейкерс

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

Да, этот способ тоже хорош, но я предпочитаю решение Ливена из-за простоты.
Eedoh

3

Я знаю, что это довольно старая ветка, но я искал что-то подобное и придумал это.

Учитывая, что у вас есть запятая строка, вы можете использовать string_split

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

Это должно вернуться

1
2
5
6

String split принимает два параметра: ввод строки и символ-разделитель.

Вы можете добавить необязательный оператор where, используя в valueкачестве имени столбца

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

производит

2
5
6

Кажется, для этого требуется MSSQL 2016 или более поздняя версия
Джонатан

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

Используйте Inфункцию SQL

Что-то вроде этого:

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.