369

I have very simple problem that I can't solve. I need to do something like this:

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

Anybody can help??

Edit

The data comes as a text file from one of our clients. It's totally unformatted (it's a single, very long line of text), but it may be possible to do so in Excel. But it's not practical for me, because I will need to use these values in my sql query. It's not convenient to do so every time I need to run a query.

4
  • do you want to select from multiple tables or select from a single table but having a specific values to select? some thing like specific id's alone Commented Oct 14, 2009 at 8:22
  • Not what you ask, but you can do it in another language. For example in PowerShell, you can do $d = (1, 1, 1, 2, 5, 1, 6) | sort -Unique to get the distinct values in an array $d. Easy to extend to a file-to-file tool. Commented Dec 11, 2017 at 10:42
  • Is the important thing here to get a distinct list of those values, or to get that list of values into SQL? As @JeppeStigNielsen says, there are other ways to get distinct values from a text list that doesn't involve SQL. I came here looking for how to get a list of values into an SQL script that references other tables. Commented Dec 10, 2018 at 23:53
  • the VALUES ( (1), (2), (3) ) AS X(Value) is the correct answer, please update it Commented Oct 27, 2020 at 10:24

16 Answers 16

695

Available only on SQL Server 2008 and over is row-constructor in this form:
You could use

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

For more information see:

Sign up to request clarification or add additional context in comments.

4 Comments

Side-note: X is alias for table name and a is alias for column name ;).
This is the more correct answer compared to the one currently selected
This is the most generic way, I was spoiled by unnest(ARRAY[]) in pgsql and now banging head to make FROM accept minor values as row records in sqlserver, and here it is. Happy to know.
Better answer due to column and table alias
164

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

In your case :

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

2 Comments

I know "select *" is considered bad form, but is there any reason not to use select * in this case? Because that duplication of FieldName1, FieldName2, ..., FieldNameN is grotesque.
@Pxtl There is no reason to not use "Select *". I have rewritten those field's names to be more clear. Also, you does not maybe need "Distinct" keyword .
108

Simplest way to get the distinct values of a long list of comma delimited text would be to use a find an replace with UNION to get the distinct values.

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

Applied to your long line of comma delimited text

  • Find and replace every comma with UNION SELECT
  • Add a SELECT in front of the statement

You now should have a working query

10 Comments

no, no, I have a list of several hundreds of values, manually it would be torture
where does that list come from? It might be way easier to just copy /paste that list in Excel and extract the distinct values there using a simple crosstab.
btw, find and replace might also take you a long way. Replace every comma with union select, add a select in front and you should have a working query cfr the union I showed.
this stuff with replacing commas with select union works like a charm Thanks a lot :)
For performance reasons, I'd recommend Union-All, then Group-By or use Distinct in your outer select.
|
49

Have you tried using the following syntax?

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

1 Comment

an anonymous user suggested to edit the code to: SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
22

If you want to select only certain values from a single table you can try this

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

eg:

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

if you want to select from multiple tables then you must go for UNION.

If you just want to select the values 1, 1, 1, 2, 5, 1, 6 then you must do this

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

2 Comments

I don't need to select from a table, but from this list of values (in brackets). That's the main problem (selecting from comma separated array of values, not from a table)
that case, like we have DUAL table in Oracle, you can make use of the same. But since there is no DUAL then you will have to go the union way. You can try another method, as you mentioned you have comma separated array of values, why don't you insert them to a table and then use a neat sql select query, instead of using so many sql unions.
20

PostgreSQL gives you 2 ways of doing this:

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

or

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

using array approach you can also do something like this:

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

2 Comments

Although the question does specify MSSQL... :)
@halfer The first answer given here worked for me, using MSSQL 2016 while the other answers didn't. 7 years later
14

I know this is a pretty old thread, but I was searching for something similar and came up with this.

Given that you had a comma-separated string, you could use string_split

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

This should return

1
2
5
6

String split takes two parameters, the string input, and the separator character.

you can add an optional where statement using value as the column name

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

produces

2
5
6

3 Comments

This seems to require MSSQL 2016 or later: learn.microsoft.com/en-us/sql/t-sql/functions/…
@Sam Yes, this is SQL Server, per the original question's tags
@Jonathan Yes, given the age of the question, It wouldn't have helped the original poster, but I figured someone might stumble upon it, as I did, and find it helpful.
8

This works on SQL Server 2005 and if there is maximal number:

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)

3 Comments

+1 neat but it is limited to the amount of rows in syscomments cross joined with itself. In my case to 294849. (and you forgot distinct.)
You can cross join once more, but replacing commas is much faster solution.
Yeah, this way is good also, but I prefer Lieven's solution, because of simplicity.
6

Using GROUP BY gives you better performance than DISTINCT:

SELECT *
FROM
(
    VALUES
        (1),
        (1),
        (1),
        (2),
        (5),
        (1),
        (6)
) AS A (nums)
GROUP BY A.nums;

Comments

2

If you need an array, separate the array columns with a comma:

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

Comments

1

Select user id from list of user id:

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

Comments

1

If it is a list of parameters from existing SQL table, for example ID list from existing Table1, then you can try this:

select distinct ID
      FROM Table1
      where 
      ID in (1, 1, 1, 2, 5, 1, 6)
ORDER BY ID;

Or, if you need List of parameters as a SQL Table constant(variable), try this:

WITH Id_list AS (
     select ID
      FROM Table1
      where 
      ID in (1, 1, 1, 2, 5, 1, 6)
)
SELECT distinct * FROM Id_list
ORDER BY ID;

Comments

0

Another way that you can use is a query like this:

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

Comments

0

I create a function on most SQL DB I work on to do just this.

CREATE OR ALTER FUNCTION [dbo].[UTIL_SplitList](@parList Varchar(MAX),@splitChar Varchar(1)=',') 
  Returns @t table (Column_Value varchar(MAX))
  as
  Begin
    Declare @pos integer 
    set @pos = CharIndex(@splitChar, @parList)
    while @pos > 0
    Begin
      Insert Into @t (Column_Value) VALUES (Left(@parList, @pos-1))
      set @parList = Right(@parList, Len(@parList) - @pos)
      set @pos = CharIndex(@splitChar, @parList)
    End
    Insert Into @t (Column_Value) VALUES (@parList)
    Return
  End

Once the function exists, it is as easy as

SELECT DISTINCT 
    *
FROM 
    [dbo].[UTIL_SplitList]('1,1,1,2,5,1,6',',') 

Comments

-3

A technique that has worked for me is to query a table that you know has a large amount of records in it, including just the Row_Number field in your result

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

will return a result set of 10000 records from 1 to 10000, use this within another query to give you the desired results

Comments

-6

Use the SQL In function

Something like this:

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

Works a treat in ArcGIS

1 Comment

This SELECT generates a syntax error with SQL Server.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.