source

여기서 쉼표로 구분된 값을 포함하는 열의 값

nicesource 2023. 11. 5. 14:45
반응형

여기서 쉼표로 구분된 값을 포함하는 열의 값

열에 값이 포함된 항목을 선택하는 SQL Server 2008용 SQL 문을 작성하려고 합니다. 이제 열 내의 값은 쉼표로 구분된 목록입니다(일반적으로 항목이 하나만 있을 수 있고 선행 쉼표가 없을 수 있음). 예를 들어 In checking에서 "이 값이 목록 내 어딘가에 포함되어 있습니까?"입니다.

COLUMN = Cat, Dog, Sparrow, Trout, Cow, Seahorse
Does COLUMN contain Cat? YES
Does COLUMN contain horse? NO
Does COLUMN contain Sheep? NO

아니면

COLUMN = Mouse
Does COLUMN contain Hare? NO
Does COLUMN contain Mouse? YES

기타

난 내가 그걸 사용할 수 있을거라 생각했어요이와 같은 IN' 키워드

SELECT id_column FROM table_name WHERE 'Cat' IN COLUMN

열에 일련의 쉼표로 구분된 값 중 하나가 포함되어 있는지만 확인할 수 있기 때문에 이 방법은 사용할 수 없습니다.

또한 CONSE() 또는 'LIKE'를 이 예로 사용할 수 없습니다. 위의 예에서는 전체 문자열이 'Seahorse'에 말을 포함하므로 'horse'에 대한 값을 반환하고, 바늘과 쉼표를 검색할 수 없습니다('horse'를 찾는 경우 검색은 'horse'가 됨). 항목이 목록 끝에 있는 경우에는 어떻게 됩니까?그리고 쉼표와 바늘을 검색할 수 없습니다('말'을 찾고 있다면 검색은 '말'일 것입니다). 항목이 목록의 첫 번째 항목인 경우에는 어떻게 됩니까?그리고 둘 다 사용할 수 없습니다. 만약 항목이 유일한(단일) 항목이라면요?

까다로운 시나리오가 하나 있습니다.목록 '17,34,400,12'에서 '40'을 찾는다면 '40'을 찾아서 잘못된 입력을 반환할 것입니다.이를 통해 모든 솔루션을 해결할 수 있습니다.

WHERE (',' + RTRIM(MyColumn) + ',') LIKE '%,' + @search + ',%'
WHERE
      MyColumn LIKE '%,' + @search + ',%' --middle
      OR
      MyColumn LIKE @search + ',%' --start
      OR
      MyColumn LIKE '%,' + @search --end
      OR 
      MyColumn =  @search --single (good point by Cheran S in comment)
SELECT * FROM TABLENAME WHERE FIND_IN_SET(@search, column)

열에 목록 항목 사이에 공백이 있는 경우

SELECT * FROM TABLENAME WHERE FIND_IN_SET(@search, REPLACE(column, ' ', ''))

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

DECLARE @search VARCHAR(10);
SET @search = 'Cat';

WITH T(C)
AS
(
SELECT 'Cat, Dog, Sparrow, Trout, Cow, Seahorse'
)
SELECT *
FROM T 
WHERE ', ' + C + ',' LIKE '%, ' + @search + ',%'

이렇게 하려면 물론 모든 검색에 대해 전체 테이블 검색이 필요합니다.

select *
from YourTable
where ','+replace(col, ' ', '')+',' like '%,Cat,%'

다른 포럼에서 답을 찾았는데, 완벽하게 작동합니다.10개만 있으면 1개를 찾는데 문제가 없습니다.

WHERE tablename REGEXP "(^|,)@search(,|$)"

여기서 찾았어요.

이 경우 가장 좋은 해결책은 서로 다른 행에 쉼표로 구분된 값을 갖도록 테이블을 정규화하는 것입니다(First normal form 1NF) http://en.wikipedia.org/wiki/First_normal_form .

따라서 CLR http://bi-tch.blogspot.com/2007/10/sql-clr-net-function-split.html 을 사용하거나 일반 SQL을 사용하여 SQL에서 멋진 분할 테이블 값 함수를 구현할 수 있습니다.

CREATE FUNCTION dbo.Split
(
    @RowData nvarchar(2000),
    @SplitOn nvarchar(5)
)  
RETURNS @RtnValue table 
(
    Id int identity(1,1),
    Data nvarchar(100)
) 
AS  
BEGIN 
    Declare @Cnt int
    Set @Cnt = 1

    While (Charindex(@SplitOn,@RowData)>0)
    Begin
        Insert Into @RtnValue (data)
        Select 
            Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

        Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
        Set @Cnt = @Cnt + 1
    End

    Insert Into @RtnValue (data)
    Select Data = ltrim(rtrim(@RowData))

    Return
END

그러면 다음을 사용하여 정규화된 출력을 쿼리할 수 있습니다.cross apply

select distinct a.id_column
from   MyTable a cross apply
       dbo.Split(A.MyCol,',') b
where  b.Data='Cat'
SELECT * FROM TABLE_NAME WHERE
        (
            LOCATE(',DOG,', CONCAT(',',COLUMN,','))>0 OR
            LOCATE(',CAT,', CONCAT(',',COLUMN,','))>0
        );

비슷한 문제에 대한 해결책을 찾고 있을 때 이 사실을 알게 되었습니다.SQL에는 CONTENS라는 새로운 키워드가 있습니다. 사용할 수 있습니다.자세한 내용은 http://msdn.microsoft.com/en-us/library/ms187787.aspx 을 참조하십시오.

콤마로 구분된 항목 수를 알 수 없으므로 'charindex' 및 'substring' SQL Server 함수로 함수를 만들어야 할 수도 있습니다.함수에서 반환된 값을 'in' 식으로 사용할 수 있습니다.

함수를 재귀적으로 호출하거나 문자열에 더 이상 항목이 없을 때까지 항목을 검색하여 루프를 생성할 수 있습니다.함수에 대한 모든 호출은 이전에 찾은 인덱스를 다음 호출의 시작점으로 사용합니다.첫 번째 통화는 0시에 시작합니다.

문자열이 아닌 ID를 알고 있는 경우 다음 방법을 사용합니다.

where mylookuptablecolumn IN (myarrayorcommadelimitedarray)

내 배열이나 코메다로 제한된 배열이 문자열 따옴표에 들어가지 않도록 해야 합니다.

A or B를 원할 경우 작동하지만 A not a not

@tbaxter120에서 제안하는 까다로운 솔루션도 좋지만 이 기능을 사용하여 매력적으로 작동합니다. pString은 구분 문자열이고 pDelimiter는 구분 문자입니다.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER FUNCTION [dbo].[DelimitedSplit]
--===== Define I/O parameters
        (@pString NVARCHAR(MAX), @pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
     -- enough to cover VARCHAR(8000)
  WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
       E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
       E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
 cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
                     -- for both a performance gain and prevention of accidental "overruns"
                 SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                 SELECT 1 UNION ALL -- does away with 0 base CTE, and the OR condition in one go!
                 SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
                ),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
                 SELECT s.N1,
                        ---ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
                        ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,50000)
                   FROM cteStart s
                )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = SUBSTRING(@pString, l.N1, l.L1)
   FROM cteLen l

;

예를 들어, 아래와 같이 where 절에 호출할 수 있습니다.

WHERE [fieldname] IN (SELECT LTRIM(RTRIM(Item)) FROM [dbo].[DelimitedSplit]('2,5,11', ','))

도움이 되길 바랍니다.

여기서 쉼표로 구분된 값을 포함하는 열의 값이 여러 쉼표로 구분된 검색

            declare @d varchar(1000)='-11,-12,10,121'

            set @d=replace(@d,',',',%'' or '',''+a+'','' like ''%,')

            print @d
            declare @d1 varchar(5000)=
            'select * from (
            select ''1,21,13,12'' as a
            union
            select ''11,211,131,121''
            union
            select ''411,211,131,1211'') as t
             where '',''+a+'','' like ''%,'+@d+ ',%'''

             print @d1
             exec (@d1)

tbaxter120이 제안한 솔루션은 효과가 있었지만 MySQL & Oracle & MSSQL에서 모두 지원할 수 있는 무언가가 필요했습니다. 여기 있습니다.

WHERE (CONCAT(',' ,CONCAT(RTRIM(MyColumn), ','))) LIKE CONCAT('%,' , CONCAT(@search , ',%'))

SQL Server 2016 이상인 경우에만 해당 - STRING_SPLIT 사용

SELECT Column From Table 
WHERE EXISTS (SELECT *  FROM STRING_SPLIT(Column , ',') WHERE value IN ('Cat'));

언급URL : https://stackoverflow.com/questions/5611715/where-value-in-column-containing-comma-delimited-values

반응형