【问题标题】:How to retrieve records using comma separated values with IN clause?如何使用带有 IN 子句的逗号分隔值检索记录?
【发布时间】:2020-10-23 19:59:09
【问题描述】:

我想从完整的表列表中检索某些记录。在这里,我使用带有 IN 子句的逗号分隔值。表格行如下所示:

这是我的 SQL 查询,但查询完成时结果集为空`

DECLARE @input VARCHAR(1000) = '2,3,17,10,16'
SELECT * FROM locations
WHERE
  east_zone in (SELECT VALUE FROM string_split(@input,','))
OR 
west_zone in (SELECT VALUE FROM string_split(@input,','))

感谢您的帮助!

【问题讨论】:

  • 停在那里。在 SQL 表中存储 CSV 通常是个坏主意。尝试根据另一个 CSV 列表搜索一个 CSV 列表并不是一个好主意。尝试规范化您的数据,以便您可以利用原生 SQL 函数。
  • 该错误是因为您提供的分隔符的长度为 0 而不是 1 ('')。如果你想用逗号分割,那么你需要传递一个逗号作为分隔符的参数,例如string_split(@input,',')。但是,这无论如何都行不通,您还需要拆分列数据,而这一切都是一种糟糕的方法。您的东/西值会更好地存储在单独的表中
  • @GarethD 感谢您发现语法错误。我已经更新了我的问题。我们如何将 csv 列数据拆分为temp 表并进行相应查询?
  • 如果用户提供 (10,22) 并且eastzone 存储为 (17,10,8,79,74,22),那么预期的输出是什么
  • @GeorgeJoseph 它应该返回唯一的行

标签: sql sql-server delimiter where-in number-with-delimiter


【解决方案1】:

虽然这可以实现,但我会要求您重新考虑您的数据模型。在数据库中存储逗号分隔的 ids/references 列表是个坏主意。我强烈支持蒂姆·比格莱森的 cmets

替代方案是将区域标题列表存储在单独的表中。

这是实现此目的的一种方法

with data
  as (select 'model_check_holding' as col1,'1,2,3,4,5' as str union all
      select 'model_cash_holding'  as col1,'5,8,9' as str 
     )
    ,split_data
     as (select *
           from data
         cross apply string_split(str,',') 
        )
     ,user_input
      as(select '2,8,1' as input_val)
select *
 from split_data
where value in (select x.value 
                 from user_input 
                 cross apply string_split(input_val,',') x
                ) 
+---------------------+-----------+-------+
|        col1         |    str    | value |
+---------------------+-----------+-------+
| model_check_holding | 1,2,3,4,5 |     1 |
| model_check_holding | 1,2,3,4,5 |     2 |
| model_cash_holding  |     5,8,9 |     8 |
+---------------------+-----------+-------+

dbfiddle 链接 https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=1cc9b224e443369744df19c1d7a7d789

【讨论】:

    【解决方案2】:

    蒂姆是 110% 正确的。您的数据模型完全搞砸了——不仅将多个值存储在分隔字符串中。但也将字符串数字作为字符串。错,错,错。

    但是,如果您被其他人的设计选择非常、非常、非常糟糕,您确实有一个选择:

    DECLARE @input VARCHAR(1000) = '2,3,17,10,16';
    
    SELECT l.*
    FROM locations l
    WHERE EXISTS (SELECT 1
                  FROM string_split(@input, ',') s1 JOIN
                       string_split(concat(l.east_zone, ',', l.west_zone), ',') l
                       ON s1.value = l.value
                 );
    

    我确实推荐这种方法。在您修复数据模型之前,我只是建议将其作为权宜之计。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 2015-02-20
      相关资源
      最近更新 更多