从一个表中选择一个逗号分隔的值,并使用 SQL Server 中的函数在另一个表中的 where 条件中使用它

Posted

技术标签:

【中文标题】从一个表中选择一个逗号分隔的值,并使用 SQL Server 中的函数在另一个表中的 where 条件中使用它【英文标题】:Select a comma-separated value from one table and use it in where condition in another table using Functions in SQL Server 【发布时间】:2018-07-14 20:31:05 【问题描述】:

我有一张表#table1,列有num, codes

num codes
----------------------------
1   44.00,2724,02.10,50.02  
2   786.59,44.0

还有另一个表#table2,它从代码列中删除重复项并将其保存如下:

sno codes
----------
1   44.00
2   2724
3   02.10
4   50.02
5   786.59

现在我想选择#table1 中的每个逗号分隔值,并使用: 分隔符从#table2 打印其适当的sno

例如:

#table1 中第一行的结果:1:2:3:4 #table1 中第二行的结果:5:1

【问题讨论】:

select * from #table1 t1 left join #table2 t2 ON CHARINDEX(t2.codes, t1.codes) > 0 但在最后 2 行而不是 5,1 中显示 1,5 order by t1.num, CHARINDEX(t2.codes, t1.codes) asc 它可以工作@artm 谢谢 【参考方案1】:

一种方法是加入#table1#table2,条件是后者的代码之一出现在第一个的CSV 列表中。然后,我们可以使用FOR XML PATH 进行汇总,以获得第一个表中每个数字的匹配sno 值列表。

SELECT
    t1.codes,
    STUFF((
      SELECT ',' + CONVERT(varchar(10), t2.sno)
      FROM table2 t2
      WHERE ',' + t1.codes + ',' LIKE '%,' + t2.codes + ',%'
      ORDER BY CHARINDEX(t2.codes, t1.codes)
      FOR XML PATH('')), 1, 1, '') as list
FROM table1 t1;

codes   list
1       44.00,2724,02.10,50.02  1,2,3,4
2       786.59,44.00            5,1

Demo

我在构建 CSV 时在此处进行了一些转换,但您可能需要做更多或更少的转换,具体取决于列的类型。特别是,我假设您所有的数字数据实际上都存储为文本。如果不是,那么上述查询可能不会产生您想要的完全匹配(例如,44.00 不会匹配 44,即使两者实际上是相同的数字)。

连接条件使用了一个技巧。以下是使用硬编码数据的 LIKE 表达式示例:

WHERE ',44.00,2724,02.10,50.02,' LIKE '%,2724,%'

换句话说,我们搜索位于#table1的给定记录中CSV字符串中任意位置的数字,两边都有逗号。

【讨论】:

我正在使用 sql server 2012 @tim @AshwanthKA 还有...?我的查询绝对应该在 SQL Server 2012 上运行,没有问题。查看演示。 WITH table1 AS ( SELECT 1 AS num, '44.00,2724,02.10,50.02' AS codes UNION ALL SELECT 2, '786.59,44.00' ), table2 AS ( SELECT 1 AS sno, '44.00' AS codes UNION ALL SELECT 2, '2724' UNION ALL SELECT 3, '02.10' UNION ALL SELECT 4, '50.02' UNION ALL SELECT 5, '786.59' ) 我的代码值可能会在每次执行时有所不同,您将其默认设置为如何将其更改为从运行时获取 我不明白你的评论。如果您的数据有问题导致上述查询无法正常工作,那么您有责任修复它。 在结果语句的第二行我需要结果为 5,1 而不是 1,5 ?@tim【参考方案2】:

如果list 列中的顺序很重要,您可以使用递归 cte。这是一个示例:

with t1 as (
    select
        *
    from
        (values (1, '44.00,2724,02.10,50.02')
            , (2, '786.59,44.0')
        ) t (num, codes)
)
, t2 as (
    select
        *
    from
        (values (1, 44.00)
            , (2, 2724)
            , (3, 02.10)
            , (4, 50.02)
            , (5, 786.59)
        )t (sno, codes)
)
, rcte as (
    select 
        num, codes = cast(codes + ',' as varchar(8000)), charindex(',', codes) ci, list = cast('' as varchar(8000))
    from 
        t1
    union all
    select
        num, cast(stuff(a.codes, 1, ci, '') as varchar(8000)), charindex(',', stuff(a.codes, 1, ci, '')), cast(concat(a.list, ':', b.sno) as varchar(8000))
    from
        rcte a
        join t2 b on substring(a.codes, 1, ci - 1) = b.codes
    where
        len(a.codes) > 0
)
select
    num, list = stuff(list, 1, 1, '')
from
    rcte
where
    ci = 0
order by num

输出:

num       list
--------------
1         1:2:3:4
2         5:1

【讨论】:

我需要这个而不使用 with 声明 这是一个recursive CTE。如果没有with 声明,您将无法使用它。在这种情况下,您需要使用@Tim Biegeleisen 解决方案 我需要一个函数来动态发送数据

以上是关于从一个表中选择一个逗号分隔的值,并使用 SQL Server 中的函数在另一个表中的 where 条件中使用它的主要内容,如果未能解决你的问题,请参考以下文章

sql/oracle 选择用逗号分隔的值并分组

如何把SQL数据表中一个字段的值按逗号分隔存入另外一个表,并删除重复记录?

如何将表中列中的逗号分隔值放入 SQL IN 运算符?

Oracle PL/SQL 程序在源表中拆分逗号分隔的数据并推送到目标表中

sql server里如何将一组用逗号分隔的字符串分解并插入到另一张表中,比如:11873,27827, 也可能是好多

MySQL - 如何选择表中的行,其中 id 值位于另一个表中的逗号分隔字段中?