【问题标题】:SQL server query to search and stuff multiple rows用于搜索和填充多行的 SQL 服务器查询
【发布时间】:2021-05-12 02:57:55
【问题描述】:

我有一张像这样的employee_table

org     employeeid (int)    firstname   lastname
1234    56788934            Suresh      Raina
1234    56793904            Virat       Kohli

然后我有 project_table 是这样的

Project     members (varchar)
A123        56788934,56793900

现在我需要像这样在一行中获取相应的员工姓名和东西。

Project     members (varchar)
A123        Suresh Raina, Virat Kohli

我在下面写了不起作用的查询。请帮忙。

SELECT project,
   (
            SELECT   message_text = Stuff(
                     (
                            SELECT ', ' + Concat(firstname,' ',lastname)
                            FROM   employee_table t1
                            WHERE  t1.org = t2.org
                            AND    CONVERT(VARCHAR,t1.userid) IN (Concat('''',Replace(pt.members,',',''','''),'''')) --adding single quotes at start and end of each number
                                   FOR xml path ('')) , 1, 1, '')
            FROM     employee_table t2
            WHERE    t2.userid IN
            group BY org;) FROM project_table pt 

【问题讨论】:

  • 您的 SQL Server 版本是多少?
  • 为什么它不起作用?它会出错吗?它会给出不正确的结果吗?
  • 在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:stackoverflow.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上面#1 中的样本数据。 (4) 你的 SQL Server 版本 (SELECT @@version;)
  • 修复您的设计,不要在数据库中存储分隔数据。解决这个问题,您的问题就会消失。
  • CONVERT(VARCHAR,t1.userid) 始终指定 (n)varchar 的长度

标签: sql sql-server split string-aggregation stuff


【解决方案1】:

这是 SQL Server 2017 及更高版本的解决方案。

它使用了 SQL Server 2017 中提供的一对方便的函数:

  • STRING_SPLIT()
  • STRING_AGG()

方法 #2 涵盖 SQL Server 2008 及更高版本的解决方案。

SQL

-- DDL and sample data population, start
DECLARE @employee TABLE (org INT, employeeid INT, firstname VARCHAR(20), lastname VARCHAR(30));
INSERT INTO @employee (org, employeeid, firstname, lastname) VALUES
(1234, 56788934, 'Suresh', 'Raina'),
(1234, 56793904, 'Virat', 'Kohli');

DECLARE @project TABLE (project CHAR(4), members VARCHAR(MAX));
INSERT INTO @project (project, members) VALUES
('A123', '56788934,56793904');
-- DDL and sample data population, end

-- Method #1, SQL Server 2017 onwards
SELECT p.project, STRING_AGG(CONCAT(e.firstname, SPACE(1), e.lastname), ', ') AS members
FROM @project AS p CROSS APPLY STRING_SPLIT(members, ',') AS s
    INNER JOIN @employee AS e ON s.value = e.employeeid
GROUP BY p.project;

-- Method #2, SQL Server 2008 onwards
DECLARE @separator CHAR(1) = ',';

;WITH rs AS
(
    SELECT *
      , TRY_CAST('<root><r><![CDATA[' + 
         REPLACE(members, @separator, ']]></r><r><![CDATA[') + ']]></r></root>' AS XML) AS xmldata
    FROM @project
), cte AS 
(
    SELECT project
        , e.*
    FROM rs CROSS APPLY xmldata.nodes('/root/r/text()') AS t(c)
        INNER JOIN @employee AS e ON c.value('.','INT') = e.employeeid
)
SELECT project
    , STUFF((SELECT @separator + CAST(CONCAT(o.firstname, SPACE(1), o.lastname) AS VARCHAR(30)) AS [text()]
         FROM cte AS O
         WHERE O.project = C.project 
         FOR XML PATH('')), 1, 1, NULL) AS Members
FROM cte AS c
GROUP BY project;

输出

+---------+---------------------------+
| project |          members          |
+---------+---------------------------+
| A123    | Suresh Raina, Virat Kohli |
+---------+---------------------------+

【讨论】:

  • 对不起,我没有提到版本。我的 sql 版本是 2014。我没有得到问题中提到的查询的输出记录。你能给我推荐一个 sql 2014 的解决方案吗?
  • @curiousboy,我用方法 #2 更新了答案。看看吧。
猜你喜欢
  • 2018-08-21
  • 1970-01-01
  • 2018-12-05
  • 2022-09-30
  • 2011-04-15
  • 2013-01-22
  • 1970-01-01
  • 2021-01-04
  • 2021-07-05
相关资源
最近更新 更多