008-SQL Server实战经验总结:如何将一对多的两个表中的某些列合并成一行显示?

2024-08-08 13:36 008-SQL Server实战经验总结:如何将一对多的两个表中的某些列合并成一行显示?已关闭评论

需求场景

SQL Server有两个表mom_ordermom_proutingdetail,momorder中的MOMID和momproutingdetail中的MOMID是一对多的关系,momorder中的一个MOMID关联多行momproutingdetail,现在需要通过外键MOMID将mom_proutingdetail中匹配的行的procedureCodeprocedureName字段分别合并成一列显示

最终想要的效果如下:

那么如何实现上述需求呢?

分析需求

要从mom_proutingdetail表中提取所有与mom_order表中特定MOMID相关的procedureCodeprocedureName字段,并将它们合并为单个列表显示。

第一种实现方式,使用STRING_AGG关键字

可以使用SQL Server的STRING_AGG函数(需要使用的SQL Server版本支持此功能,即2017或更高版本中支持)

代码实现:

WITH CTE AS (
    SELECT 
        mo.MOMID,
        mp.procedureCode,
        mp.procedureName
    FROM mom_order mo
    INNER JOIN mom_proutingdetail mp ON mo.MOMID = mp.MOMID
)
SELECT 
    MOMID,
    STRING_AGG(procedureCode, ',') WITHIN GROUP (ORDER BY procedureCode) AS ProcedureCodes,
    STRING_AGG(procedureName, ',') WITHIN GROUP (ORDER BY procedureName) AS ProcedureNames
FROM CTE cte1
GROUP BY MOMID;
  1. WITH CTE AS ( - 使用了一个公用表表达式(Common Table Expression,简称CTE),它允许我们在查询中创建一个临时的结果集,这个结果集可以被之后的查询引用。

  2. SELECT mo.MOMID, mp.ProcedureCode, pp.ProcedureName - 这里选择了mom_order表中的MOMID字段,mom_proutingdetail表中的ProcedureCode字段,以及Proc_Procedure表中的ProcedureName字段。

  3. FROM mom_order mo - 查询从mom_order表开始,mo是给这个表起的别名。

  4. INNER JOIN mom_proutingdetail mp ON mo.MOMID = mp.MOMID - 使用INNER JOIN连接mom_ordermom_proutingdetail两个表,基于MOMID字段的匹配。mp是给mom_proutingdetail表起的别名。

  5. INNER JOIN Proc_Procedure pp ON mp.ProcedureCode=pp.ProcedureCode - 再次使用INNER JOIN连接mom_proutingdetailProc_Procedure两个表,这次基于ProcedureCode字段的匹配。pp是给Proc_Procedure表起的别名。

  6. ) - 结束CTE的定义。

  7. SELECT MOMID, - 主查询开始,选择MOMID字段。

  8. STRING_AGG(procedureCode, ',') WITHIN GROUP (ORDER BY procedureCode) AS ProcedureCodes - 使用STRING_AGG函数将与每个MOMID相关联的所有ProcedureCode值聚合到一个由逗号分隔的字符串中。WITHIN GROUP (ORDER BY procedureCode)确保了字符串中的值是按ProcedureCode排序的。

  9. ,STRING_AGG(procedureName, ',') WITHIN GROUP (ORDER BY procedureName) AS ProcedureNames - 类似地,将所有ProcedureName值聚合到一个由逗号分隔的字符串中,同时按ProcedureName排序。

  10. FROM CTE cte1 - 主查询从之前定义的CTE中获取数据,cte1是给CTE起的别名。

  11. GROUP BY MOMID; - 按MOMID字段对结果进行分组,这意味着对于每个唯一的MOMID,都会生成一行结果,其中包含该MOMID下所有相关的ProcedureCodeProcedureName的聚合字符串。

首先创建了一个CTE(公用表表达式),将两个表连接在一起。然后在主查询中,它使用STRING_AGG函数将每个MOMID下的procedureCodeprocedureName值聚合到一个逗号分隔的字符串中。

如果允许报错:

消息 8711,级别 16,状态 1,第 47 行
同一作用域中的多个已排序聚合函数具有互相不兼容的排序。

在一个查询中使用了多个STRING_AGG()函数或其他排序聚合函数,并且这些函数的排序顺序不一致时会报错。

要解决这个问题,只需要确保所有STRING_AGG()函数使用相同的排序依据和排序方向。可以通过在所有WITHIN GROUP子句中使用相同的排序键来实现,例如:

SELECT 
    MOMID,
    STRING_AGG(procedureCode, ',') WITHIN GROUP (ORDER BY procedureCode) AS ProcedureCodes,
    STRING_AGG(procedureName, ',') WITHIN GROUP (ORDER BY procedureCode) AS ProcedureNames
FROM CTE cte1
GROUP BY MOMID;

在这个修正后的查询中,两个STRING_AGG()函数都按照procedureCode进行排序。这样,即使procedureNameprocedureCode之间没有直接的排序关系,由于它们都是基于procedureCode进行排序的,因此不会产生冲突。

当然,也可以按照ProcedureName进行排序,将两个STRING_AGG()函数的排序键改为procedureName

SELECT 
    MOMID,
    STRING_AGG(procedureCode, ',') WITHIN GROUP (ORDER BY procedureName) AS ProcedureCodes,
    STRING_AGG(procedureName, ',') WITHIN GROUP (ORDER BY procedureName) AS ProcedureNames
FROM CTE cte1
GROUP BY MOMID;

这样修改后,应该可以避免再出现上述错误。

第二种实现方式,使用STUFF关键字

如果当前的SQL Server版本不支持STRING_AGG,可以使用该方法。在SQL Server 2012及更早版本中,可以使用FOR XML PATH技巧来生成逗号分隔的字符串。

代码实现:

WITH CTE AS (
    SELECT 
        mo.MOMID,
        mp.procedureCode,
        mp.procedureName
    FROM mom_order mo
    INNER JOIN mom_proutingdetail mp ON mo.MOMID = mp.MOMID
)
SELECT 
    MOMID,
    STUFF((SELECT ',' + procedureCode 
           FROM CTE cte2 
           WHERE cte1.MOMID = cte2.MOMID
           ORDER BY procedureCode
           FOR XML PATH('')), 1, 1, '') AS ProcedureCodes,
    STUFF((SELECT ',' + procedureName 
           FROM CTE cte2 
           WHERE cte1.MOMID = cte2.MOMID
           ORDER BY procedureName
           FOR XML PATH('')), 1, 1, '') AS ProcedureNames
FROM CTE cte1
GROUP BY MOMID;

上述实例中,STUFF函数用于移除第一个字符(逗号)以避免格式错误。

当前文章价值8.55元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/3646.html ,谢谢支持!

资源分享

python成功发布文章后触发生成sitemap python成功发布文章后触发生成si
Android手机如何快速接入周围无线网络 Wifi密码快速破解 Wifi工具 Android手机如何快速接入周围无
harmony初步了解类、函数和变量的定义 harmony初步了解类、函数和变量的
Android电脑局域网操作手机的工具 Android电脑局域网操作手机的工

评论已关闭!