简体   繁体   中英

Get Distinct value from a list in SQL Server

I have a DB column that has a comma delimited list:

VALUES          ID
--------------------
1,11,32          A
11,12,28         B
1                C
32,12,1          D

When I run my SQL statement, in my WHERE clause I have tried IN , CONTAINS and LIKE with varying degrees of errors and success, but none offer an exact return of what I need.

What I need is a where clause that if I'm looking for all IDs with vale of '1' (NOT the number) in the list.

Example of problem:

WHERE values like (1)

This will return A,B,C,D because 1 is included in the value (11). I would expect IDs (A,C,D).

WHERE values like (2)

This will return A,B,D because 2 is included in the value (32,28,12). I would expect zeros records.

Thanks in advance for your help!

I will begin my answer by quoting the spot-on comment given by @Jarlh above:

Never, ever store data as comma separated items. It will only cause you lots of trouble.

That being said, if you're really stuck with this design, you could use:

SELECT *
FROM yourTable
WHERE ',' + [VALUES] + ',' LIKE '%,1,%';

The trick here is convert every VALUES into something looking like:

,11,12,28,

Then, we can search for a target number with comma delimiters on both sides. Since we placed commas at both ends, then every number in the CSV list is now guaranteed to have commas around it.

If you are stuck with such a poor data model, I would suggest:

select t.*
from t
where exists (select 1
              from string_split(t.values, ',') s
              where s.value = 1
             );

Exactly i echo what jarlh and Tim says. relational model is not the right place to store comma delimited strings in table.

Here is an approach, that can likely use an index if there is one on column x

select distinct x
  from t
 cross apply string_split(t.x,',')
where value=1 /*out here you may parameterize, and also could make use of an index each if there is one in value*/ 

+---------+
|    x    |
+---------+
|       1 |
| 1,11,32 |
| 32,12,1 |
+---------+

working example https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=b9b3084f52b0f42ffd17d90427016999

--SQL Server older versions

with data
 as (
SELECT t.c.value('.', 'VARCHAR(1000)') as val
      ,y
      ,x
           FROM (
                 SELECT x1 = CAST('<t>' + 
                             REPLACE(x , ',', '</t><t>') + '</t>' AS XML)
                        ,y 
                        ,x
                   FROM t
                ) a
     CROSS APPLY x1.nodes('/t') t(c)
     )
select x,y
  from data

+---------+
|    x    |
+---------+
|       1 |
| 1,11,32 |
| 32,12,1 |
+---------+

working example https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=011a096bbdd759ea5fe3aa74b08bc895

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM