Como posso selecionar da lista de valores no SQL Server


216

Eu tenho um problema muito simples que não consigo resolver. Eu preciso fazer algo assim:

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

Alguém pode ajudar ??

Editar

Os dados são fornecidos como um arquivo de texto de um de nossos clientes. É totalmente não formatado (é uma única linha de texto muito longa), mas pode ser possível fazê-lo no Excel. Mas não é prático para mim, porque precisarei usar esses valores na minha consulta sql. Não é conveniente fazer isso sempre que preciso executar uma consulta.


você deseja selecionar em várias tabelas ou em uma única tabela, mas com valores específicos para selecionar? alguma coisa como id específico está sozinho
Anirudh Goel

Não é o que você pede, mas você pode fazê-lo em outro idioma. Por exemplo, no PowerShell, você pode fazer $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniquepara obter os valores distintos em uma matriz $d. Fácil de estender a uma ferramenta de arquivo para arquivo.
Jeppe Stig Nielsen

O importante aqui é obter uma lista distinta desses valores ou colocar essa lista de valores no SQL? Como o @JeppeStigNielsen diz, existem outras maneiras de obter valores distintos de uma lista de texto que não envolve SQL. Eu vim aqui procurando como obter uma lista de valores em um script SQL que faça referência a outras tabelas.
Rikki

Respostas:


81

A maneira mais simples de obter os valores distintos de uma longa lista de texto delimitado por vírgula seria usar uma substituição de localização por UNION para obter os valores distintos.

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

Aplicado à sua longa linha de texto delimitado por vírgula

  • Encontre e substitua cada vírgula por UNION SELECT
  • Adicione um SELECTna frente da declaração

Agora você deve ter uma consulta de trabalho


3
não, não, eu tenho uma lista de várias centenas de valores, manualmente seria tortura
Eedoh

de onde vem essa lista? Pode ser muito mais fácil copiar / colar essa lista no Excel e extrair os valores distintos usando uma tabela de referência cruzada simples.
Lieven Keersmaekers

Aliás, encontrar e substituir também pode levar um longo caminho. Substitua todas as vírgulas com a seleção de união , adicione uma seleção na frente e você deverá ter uma consulta de trabalho cfr a união que mostrei.
Lieven Keersmaekers

1
este material com a substituição vírgulas com select união funciona como um encanto Muito obrigado :)
Eedoh

5
Por motivos de desempenho, eu recomendo o Union-All e depois o Group-By ou use Distinct em sua seleção externa.
MikeTeeVee

427

Disponível apenas no SQL Server 2008 e superior, é o construtor de linhas desta forma:
Você pode usar

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

Muitos escreveram sobre, entre eles:


66
Nota lateral: Xé o alias para o nome da tabela e aé o alias para o nome da coluna;).
shA.t

11
Esta é a resposta mais correta em comparação com o selecionado
TabsNotSpaces

1
Essa é a maneira mais genérica: eu fui mimado por unnest (ARRAY []) pgsqle agora estou acenando para fazer FROM aceitar valores menores como registros de linha sqlserver, e aqui está. Feliz em saber.
Ben

1
Melhor resposta devido a alias de coluna e tabela
Alfredo A.

79

Em geral :

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 )

No seu caso :

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

Sei que "select *" é considerado uma forma incorreta, mas existe alguma razão para não usar o select * nesse caso? Porque essa duplicação de FieldName1, FieldName2, ..., FieldNameN é grotesca.
Pxtl

43

Você já tentou usar a seguinte sintaxe?

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

5
um usuário anônimo sugeriu editar o código para:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612 22/10/2015

19

Se você deseja selecionar apenas determinados valores de uma única tabela, pode tentar isso

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

por exemplo:

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

Se você deseja selecionar entre várias tabelas, deve escolher UNION.

Se você quiser apenas selecionar os valores 1, 1, 1, 2, 5, 1, 6, faça isso

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

1
Não preciso selecionar de uma tabela, mas desta lista de valores (entre colchetes). Esse é o principal problema (selecionando a partir vírgula separados matriz de valores, não a partir de uma tabela)
Eedoh

Nesse caso, como temos a tabela DUAL no Oracle, você pode fazer uso da mesma. Mas como não há DUAL, você terá que seguir o caminho da união. Você pode tentar outro método, como mencionou que possui uma matriz de valores separados por vírgula, por que não os insere em uma tabela e usa uma consulta de seleção sql pura, em vez de usar tantas uniões sql.
Anirudh Goel 14/10/09

14

O PostgreSQL fornece duas maneiras de fazer isso:

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

ou

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

usando a abordagem de array, você também pode fazer algo assim:

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

11
Embora a questão não especifica MSSQL ...:)
halfer

@halfer A primeira resposta dada aqui funcionou para mim, usando o MSSQL 2016, enquanto as outras respostas não. 7 anos depois
dustytrash 9/09/19

9

Isso funciona no SQL Server 2005 e se houver um número máximo:

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
Marcar com +1, mas é limitado à quantidade de linhas nos syscomments cruzadas entre si. No meu caso a 294849. (e você se esqueceu distinta.)
Lieven Keersmaekers

Você pode cruzar a junção mais uma vez, mas a substituição de vírgulas é uma solução muito mais rápida.
LukLed

Sim, esse caminho também é bom, mas prefiro a solução de Lieven, por causa da simplicidade.
Eedoh

3

Eu sei que este é um tópico bastante antigo, mas eu estava procurando por algo semelhante e surgiu com isso.

Como você tinha uma cadeia de caracteres separada por vírgula, poderia usar string_split

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

Isso deve retornar

1
2
5
6

A divisão de cadeia utiliza dois parâmetros, a entrada de cadeia e o caractere separador.

você pode adicionar uma instrução where opcional usando valuecomo o nome da coluna

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

produz

2
5
6

Isso parece exigir o MSSQL 2016 ou posterior: docs.microsoft.com/en-us/sql/t-sql/functions/…
Jonathan

1
@Sam Sim, este é o SQL Server, por etiquetas da pergunta original
NapkinBob

1
@ Jonathan Sim, dada a idade da pergunta, isso não teria ajudado o pôster original, mas imaginei que alguém pudesse tropeçar nele, como eu, e achei útil.
NapkinBob

2

Se você precisar de uma matriz, separe as colunas da matriz com uma vírgula:

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

0

Outra maneira que você pode usar é uma consulta como esta:

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

Selecione o ID do usuário na lista de IDs do usuário:

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

-2

Uma técnica que funcionou para mim é consultar uma tabela que você sabe que possui uma grande quantidade de registros, incluindo apenas o campo Row_Number no seu resultado

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

retornará um conjunto de resultados de 10000 registros de 1 a 10000, use-o em outra consulta para fornecer os resultados desejados


-4

Use a Infunção SQL

Algo assim:

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

Trabalha um tratamento no ArcGIS


1
Este SELECT gera um erro de sintaxe com o SQL Server.
precisa saber é
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.