【问题标题】:SQL Server equivalent to GROUP_CONCAT() [duplicate]SQL Server 等效于 GROUP_CONCAT() [重复]
【发布时间】:2013-10-07 07:09:03
【问题描述】:

我有这个数据库:

我需要为每个客户获取以下数据:

  • 客户名称
  • 合同名称
  • 项目
  • 从当月第一天到当月最后一天记录项目小时数的员工
  • 每个员工在当月记录的总小时数
  • 员工率
  • 每位员工的总费用(即员工费率 x 员工工作时间)
  • 每份合同的帐单联系人 [姓名、地址]

到目前为止,我有以下查询,但我需要实现 MySQL 的 GROUP_CONCAT( ) 的 MSSQL 版本

SELECT 

Cl.LegalName AS ClientNames,
Cr.ContractDesc AS ContractNames,
P.ProjectName AS ProjectNames,
( E.FirstName + ' ' + E.LastName ) AS EmployeeNames,
SUM( WH.HoursWorked ) AS TotalHours, 
( SUM( WH.HoursWorked ) * BR.Rate ) AS TotalCharges, 
( Ca.FirstName + Ca.LastName + ', ' + Ca.AddrLine1 ) AS BillingContacts

FROM Clients Cl
JOIN Contracts Cr
ON( Cl.ClientID = Cr.ClientID )

JOIN Projects P 
ON( Cr.ContractID = P.ContractID )

JOIN EmployeesProjects EP
ON( P.ProjectID = EP.ProjectID )

JOIN Employees E 
ON( EP.EmpID = E.EmpID )

JOIN WorkHours WH
ON( E.EmpID = WH.EmpID )

JOIN BillingRates BR
ON( E.TitleID = BR.TitleID ) AND ( E.Level = BR.Level )

JOIN ContractsContacts CC
ON( Cr.ContractID = CC.ContractID )
JOIN Contacts Ca
ON( CC.ContactID = Ca.ContactID )

WHERE WH_Month = 4
AND WH_Year = 2013

当我开始关注 this 示例时,我到了这里并停下来,因为我意识到我无法从其他子查询 (ProjectNames) 引用表别名 (Cr)。

SELECT 
Cl.LegalName AS ClientNames, 
(
    SELECT ContractDesc + ', '
    FROM Contracts Cr
    WHERE Cl.ClientID = Cr.ClientID 
    FOR XML PATH('')
) ContractNames,
(
    SELECT ProjectName + ', '
    FROM Projects P
    WHERE Cr.ContractID = P.ContractID
    FOR XML PATH('')
) ProjectNames


FROM Clients Cl

我该如何做呢?

【问题讨论】:

    标签: sql sql-server join string-aggregation


    【解决方案1】:

    尝试CROSS APPLY做你自己:

    例如:

    SELECT Cl.LegalName AS ClientNames,
    B.ContractDesc AS ContractNames,
    P.ProjectName AS ProjectNames,
    ( E.FirstName + ' ' + E.LastName ) AS EmployeeNames,
    SUM( WH.HoursWorked ) AS TotalHours, 
    ( SUM( WH.HoursWorked ) * BR.Rate ) AS TotalCharges, 
    ( Ca.FirstName + Ca.LastName + ', ' + Ca.AddrLine1 ) AS BillingContacts
    
    FROM Clients Cl
    JOIN Contracts Cr ON( Cl.ClientID = Cr.ClientID )
    JOIN Projects P ON( Cr.ContractID = P.ContractID )
    JOIN EmployeesProjects EP ON( P.ProjectID = EP.ProjectID )
    JOIN Employees E ON( EP.EmpID = E.EmpID )
    JOIN WorkHours WH ON( E.EmpID = WH.EmpID )
    JOIN BillingRates BR ON( E.TitleID = BR.TitleID ) AND ( E.Level = BR.Level )
    JOIN ContractsContacts CC ON( Cr.ContractID = CC.ContractID )
    JOIN Contacts Ca ON( CC.ContactID = Ca.ContactID ) 
    CROSS APPLY (
        SELECT Cr1.ContractDesc + ', '
        FROM Contracts Cr1
        WHERE Cl.ClientID = Cr1.ClientID 
        FOR XML PATH('')
    ) B (ContractDesc)
    WHERE WH_Month = 4 AND WH_Year = 2013
    

    【讨论】:

      【解决方案2】:

      这样做

         SELECT Cl.LegalName AS ClientNames,
         ContractNames
         FROM Clients Cl
          cross apply 
         (SELECT Cr1.ContractDesc + ', '
          FROM Contracts Cr1
            WHERE Cl.ClientID = Cr1.ClientID  For XML PATH(''))a1 (ContractNames)
      

      【讨论】:

        【解决方案3】:

        STRING_AGG 几乎等同于 MySQL 中的 GROUP_CONCAT。参考微软官方文档here

        请注意,STRING_AGG 不允许 Text 类型,因此如果要在 Text 字段上连接,则需要转换为 NVARCHAR。

        例子:

        STRING_AGG(CONVERT(NVARCHAR(2000), your_text_field_name), ',')
        

        【讨论】:

          猜你喜欢
          • 2013-05-13
          • 2012-09-15
          • 2017-11-16
          • 1970-01-01
          • 2012-02-15
          • 2012-02-10
          • 1970-01-01
          • 2016-08-22
          相关资源
          最近更新 更多