【问题标题】:how to compare a string delimited string to a column value in sql without considering sequence如何在不考虑顺序的情况下将字符串分隔的字符串与 sql 中的列值进行比较
【发布时间】:2017-05-17 12:23:31
【问题描述】:

如何在不考虑顺序的情况下将字符串分隔的字符串与sql中的列值进行比较?

假设我在 sql 列 [fruits] 中有一个值 - mango, apple, cherry... 我在 asp.net C# 中有一个列表cherry, mango, apple... 我想编写 sql 查询以便它可以匹配没有顺序的sql表。

【问题讨论】:

  • 想想如果你有 3 行 abc 而不是 1 行 a,b,c。使用逗号分隔的值几乎毫无例外地是一个糟糕的设计选择。
  • 我有水果列..我必须以逗号分隔存储...以满足我的要求
  • 请帮助pppppppp
  • 哪个版本的sql server?
  • 2014版本

标签: c# asp.net .net sql-server


【解决方案1】:

我建议你看看这个 SO question 中的精彩答案

How to split a comma-separated value to columns

也就是说,您的解决方案应该将包含单词的每一列传递给此函数,然后将其与列 ID 一起存储在表中。

所以“mango,apple,cherry”变成了一个有值的表

ColdID   Value
_______________
1      mango
1      apple
1      cherry

现在按 ColID ASC、Value ASC 对表格进行排序并比较两个表格。

【讨论】:

  • 请不要在发布的链接中使用已接受的答案。这个答案是使用循环来分割字符串,这是非常低效的。到目前为止,最好的方法是不存储分隔数据,但如果您确实在此处查看拆分选项。 sqlperformance.com/2012/07/t-sql-queries/split-strings许多选项是基于设置的,不使用循环。
【解决方案2】:

应该这样做。

DECLARE @str NVARCHAR(MAX)
,   @Delim NVARCHAR(255)

SELECT @str = 'cherry,mango,peach,apple'
SELECT @Delim = ','

CREATE TABLE #Fruits ( Fruit VARCHAR(255) )

INSERT INTO #Fruits
        ( Fruit )
    VALUES  ( 'cherry' ),
            ( 'Mango' ),
            ( 'Apple' ) ,
            ( 'Banana' )


   ;WITH lv0 AS (SELECT 0 g UNION ALL SELECT 0)
    ,lv1 AS (SELECT 0 g FROM lv0 a CROSS JOIN lv0 b) -- 4
    ,lv2 AS (SELECT 0 g FROM lv1 a CROSS JOIN lv1 b) -- 16
    ,lv3 AS (SELECT 0 g FROM lv2 a CROSS JOIN lv2 b) -- 256
    ,lv4 AS (SELECT 0 g FROM lv3 a CROSS JOIN lv3 b) -- 65,536
    ,lv5 AS (SELECT 0 g FROM lv4 a CROSS JOIN lv4 b) -- 4,294,967,296
    ,Tally_CTE (n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM lv5)

SELECT SUBSTRING(@str, N, CHARINDEX(@Delim, @str + @Delim, N) - N) AS Item
    INTO #StrTable
    FROM Tally_CTE
    WHERE N BETWEEN 1 AND DATALENGTH(@str) + DATALENGTH(@Delim)
        AND SUBSTRING(@Delim + @str, N, LEN(@Delim)) = @Delim;

--#############################################################################
-- in both
--############################################################################# 
SELECT *
    FROM #Fruits F
        JOIN #StrTable ST ON F.Fruit = ST.Item

--#############################################################################
-- in table but not string
--############################################################################# 
SELECT *
    FROM #Fruits F
        LEFT JOIN #StrTable ST ON ST.Item = F.Fruit
    WHERE ST.Item IS NULL
--#############################################################################
-- in string but not table
--############################################################################# 
SELECT *
    FROM #StrTable ST
        LEFT JOIN #Fruits F ON ST.Item = F.Fruit
    WHERE F.Fruit IS NULL
GO
DROP TABLE #Fruits
DROP TABLE #StrTable

【讨论】:

    【解决方案3】:

    您可以使用 string_split 函数来执行此操作。我在 SQL Server 2017 ctp 2.0 上对此进行了测试,但它应该也可以在 2016 年使用。

     drop table if exists dbo.Fruits;
    
    create table dbo.Fruits (
        Fruits varchar(100)
    );
    
    
    insert into dbo.Fruits (Fruits)
    values ('cherry,mango,apple'), ('peanut,cherry,mango'), 
    ('apple,cherry,mango')
    
    
    declare @str varchar(100) = 'apple,mango,cherry';
    
    select
        tt.Fruits
        , COUNT(tt.value) as Value01
        , COUNT(app.value) as Value02
    from (
        select
        *
        from dbo.Fruits f
            outer apply string_split (f.Fruits, ',') t
    ) tt
        left join string_split (@str, ',') app on tt.value = app.value
    group by tt.Fruits
    

    【讨论】:

      猜你喜欢
      • 2019-09-30
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      • 2021-11-11
      • 2012-07-10
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      相关资源
      最近更新 更多