¿Cómo puedo seleccionar de la lista de valores en SQL Server?

216

Tengo un problema muy simple que no puedo resolver. Necesito hacer algo como esto:

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

¿Alguien puede ayudar?

Editar

Los datos vienen como un archivo de texto de uno de nuestros clientes. Está totalmente sin formato (es una sola línea de texto muy larga), pero puede ser posible hacerlo en Excel. Pero no es práctico para mí, porque necesitaré usar estos valores en mi consulta sql. No es conveniente hacerlo cada vez que necesito ejecutar una consulta.

Eedoh
fuente
¿Desea seleccionar de varias tablas o seleccionar de una sola tabla pero tiene valores específicos para seleccionar? algo así como identificación específica solo
Anirudh Goel
No es lo que pides, pero puedes hacerlo en otro idioma. Por ejemplo, en PowerShell, puede hacer $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniquepara obtener los valores distintos en una matriz $d. Fácil de extender a una herramienta de archivo a archivo.
Jeppe Stig Nielsen
¿Es lo importante aquí obtener una lista distinta de esos valores, o llevar esa lista de valores a SQL? Como dice @JeppeStigNielsen, hay otras formas de obtener valores distintos de una lista de texto que no involucra SQL. Vine aquí buscando cómo obtener una lista de valores en un script SQL que haga referencia a otras tablas.
Rikki

Respuestas:

81

La manera más simple de obtener los valores distintos de una larga lista de texto delimitado por comas sería utilizar un reemplazo con UNION para obtener los valores distintos.

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

Aplicado a su larga línea de texto delimitado por comas

  • Encuentra y reemplaza cada coma con UNION SELECT
  • Agregue un SELECTdelante de la declaración

Ahora debería tener una consulta de trabajo

Lieven Keersmaekers
fuente
3
No, no, tengo una lista de varios cientos de valores, manualmente sería una tortura
Eedoh,
¿De dónde viene esa lista? Puede ser mucho más fácil copiar / pegar esa lista en Excel y extraer los valores distintos allí usando una tabla cruzada simple.
Lieven Keersmaekers
por cierto, buscar y reemplazar también puede llevarlo lejos. Reemplace cada coma con selección de unión , agregue una selección al frente y debería tener una consulta de trabajo con la unión que mostré.
Lieven Keersmaekers
1
esto con reemplazar comas por una unión selecta funciona de
maravilla
55
Por razones de rendimiento, recomendaría Union-All, luego Group-By o use Distinct en su selección externa.
MikeTeeVee
427

Disponible solo en SQL Server 2008 y versiones posteriores es el constructor de filas de esta forma:
podría usar

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

Muchos escribieron sobre, entre ellos:

pm.
fuente
66
Nota al margen: Xes alias para el nombre de la tabla y aes alias para el nombre de la columna;).
shA.t
11
Esta es la respuesta más correcta en comparación con la seleccionada actualmente
TabsNotSpaces
1
Esta es la forma más genérica, me descompuso unnest (ARRAY []) en pgsqly ahora golpeando la cabeza para hacer que FROM acepte valores menores como registros de fila sqlserver, y aquí está. Feliz de saber.
Ben
1
Mejor respuesta debido al alias de columna y tabla
Alfredo A.
79

En general :

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 )

En tu caso :

Select 
  distinct
  TempTableName.Field1 
From 
  (
  VALUES
    (1), 
    (1), 
    (1), 
    (2), 
    (5), 
    (1), 
    (6)
  ) AS TempTableName (Field1)
Ardalan Shahgholi
fuente
1
Sé que "select *" se considera mala forma, pero ¿hay alguna razón para no usar select * en este caso? Debido a que esa duplicación de FieldName1, FieldName2, ..., FieldNameN es grotesca.
Pxtl hace
@Pxtl No hay razón para no usar "Seleccionar *". He reescrito los nombres de esos campos para que sean más claros. Además, quizás no necesite la palabra clave "Distinto".
Ardalan Shahgholi
43

¿Has intentado usar la siguiente sintaxis?

select * from (values (1), (2), (3), (4), (5)) numbers(number)
Robba
fuente
55
un usuario anónimo sugirió editar el código a:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612
19

Si desea seleccionar solo ciertos valores de una sola tabla, puede probar esto

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

p.ej:

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

Si desea seleccionar entre varias tablas, debe elegir UNION.

Si solo desea seleccionar los valores 1, 1, 1, 2, 5, 1, 6, entonces debe hacer esto

select 1 
union select 1 
union select 1 
union select 2 
union select 5 
union select 1 
union select 6
Anirudh Goel
fuente
1
No necesito seleccionar de una tabla, sino de esta lista de valores (entre paréntesis). Ese es el problema principal (selección de una matriz de valores separados por comas, no de una tabla)
Eedoh
En ese caso, como tenemos una tabla DUAL en Oracle, puede hacer uso de la misma. Pero como no hay DUAL, deberá seguir el camino de la unión. Puede probar otro método, como mencionó que tiene una matriz de valores separados por comas, ¿por qué no los inserta en una tabla y luego usa una consulta ordenada de selección SQL, en lugar de usar tantas uniones SQL?
Anirudh Goel
14

PostgreSQL le ofrece 2 formas de hacer esto:

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

o

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

usando el enfoque de matriz también puede hacer algo como esto:

SELECT DISTINCT * FROM (select unnest(string_to_array('a;b;c;d;e;f;a;b;d', ';'))) AS tbl(col1)
Arek
fuente
11
Aunque la pregunta especifica MSSQL ...:)
suspender el
@halfer La primera respuesta dada aquí funcionó para mí, usando MSSQL 2016 mientras que las otras respuestas no. 7 años después
dustytrash
9

Esto funciona en SQL Server 2005 y si hay un 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)
LukLed
fuente
2
+1 ordenado, pero está limitado a la cantidad de filas en syscomments cruzadas entre sí. En mi caso al 294849. (y te olvidaste distinto.)
Lieven Keersmaekers
Puede unir una vez más, pero reemplazar comas es una solución mucho más rápida.
LukLed
Sí, este camino también es bueno, pero prefiero la solución de Lieven, por simplicidad.
Eedoh
3

Sé que este es un hilo bastante antiguo, pero estaba buscando algo similar y se me ocurrió esto.

Dado que tenía una cadena separada por comas, podría usar string_split

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

Esto debería volver

1
2
5
6

La división de cadena toma dos parámetros, la entrada de cadena y el carácter separador.

puede agregar una instrucción where opcional usando valuecomo nombre de columna

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

produce

2
5
6
Servilleta
fuente
Esto parece requerir MSSQL 2016 o posterior: docs.microsoft.com/en-us/sql/t-sql/functions/…
Jonathan
1
@Sam Sí, este es SQL Server, según las etiquetas de la pregunta original
NapkinBob
1
@ Jonathan Sí, dada la edad de la pregunta, no habría ayudado al póster original, pero pensé que alguien podría tropezar con él, como lo hice yo, y encontrarlo útil.
NapkinBob
2

Si necesita una matriz, separe las columnas de la matriz con una coma:

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

Otra forma que puede usar es una 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);
shA.t
fuente
0

Seleccione la identificación de usuario de la lista de identificación de usuario:

SELECT * FROM my_table WHERE user_id IN (1,3,5,7,9,4);
Biplob Das
fuente
-2

Una técnica que me ha funcionado es consultar una tabla que sabe que tiene una gran cantidad de registros, incluido solo el campo Row_Number en su resultado

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

devolverá un conjunto de resultados de 10000 registros de 1 a 10000, use esto dentro de otra consulta para obtener los resultados deseados

Jwalter
fuente
-4

Usa la Infunción SQL

Algo como esto:

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

Funciona un regalo en ArcGIS

usuario3059384
fuente
1
Este SELECT genera un error de sintaxis con SQL Server.
JohnH