0

我有一个像这样的 3 个不同表的联合表。

Select DoctorTable.Doctor, NurseTable.Nurse , PatientTable.Patents 

FROM PatientTable

LEFT JOIN DoctorTable on DoctorTable.DoctorCode = PatientTable.DoctorCode

LEFT JOIN NurseTable on DoctorTable.DoctorCode = NurseTable.DoctorCode


Patient     Doctor        Nurse
John        Peter         Mary
John        Peter         Amy
Kate        Terry         Mary
Kate        Leo           Ivy
Paul        NULL          NULL
Emily       NULL          NULL

我想在“医生”列中用逗号连接具有相同值的行,得到下面的结果

Patient     Doctor        Nurse
John        Peter         Mary, Amy
Kate        Terry, Leo    Mary, Ivy
Paul        Null          Null
Emily       NULL          NULL

因为我还有一些列要加入这个表,并且还需要用','对行进行分组,所以使用 FOR XML PATH('') 对每一列进行分组会很慢。那么如何有效地对这个表进行分组呢?

4

1 回答 1

1

我认为答案是使用一个聚合函数来连接组中的行。太糟糕了 TSQL 没有一个(这有多难?),但如果您不介意使用 SQLCLR,这里是如何在 MSDN 中使用 .NET 创建用户定义的聚合连接函数:

MSDN 字符串实用函数示例

<Serializable(), Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Microsoft.SqlServer.Server.Format.UserDefined, IsInvariantToNulls:=True, IsInvariantToDuplicates:=False, IsInvariantToOrder:=False, MaxByteSize:=8000)> _
Public Class Concatenate : Implements Microsoft.SqlServer.Server.IBinarySerialize

    Private Builder As StringBuilder

    Public Sub Init()
        Builder = New StringBuilder
    End Sub

    Public Sub Accumulate(ByVal value As SqlString)
        If value.IsNull Then Return
        Builder.Append(",").Append(value.Value)
    End Sub

    Public Sub Merge(ByVal other As Concatenate)
        Builder.Append(other.Builder)
    End Sub

    Public Function Terminate() As SqlString
        If Builder Is Nothing Then Return New SqlString("")
        Return New SqlString(Builder.ToString.Substring(1))
    End Function

    Public Sub Read(ByVal r As BinaryReader) Implements Microsoft.SqlServer.Server.IBinarySerialize.Read
        If r Is Nothing Then Throw New ArgumentNullException("r")
        Builder = New StringBuilder(r.ReadString())
    End Sub

    Public Sub Write(ByVal w As BinaryWriter) Implements Microsoft.SqlServer.Server.IBinarySerialize.Write
        If w Is Nothing Then Throw New ArgumentNullException("w")
        w.Write(Builder.ToString())
    End Sub

End Class

然后,您可以执行以下操作:

SELECT PatientCode, Patient, dbo.Concatenate(Doctor), dbo.Concatenate(Nurse) 
FROM PatientTable
LEFT JOIN DoctorTable on DoctorTable.DoctorCode = PatientTable.DoctorCode
LEFT JOIN NurseTable on DoctorTable.DoctorCode = NurseTable.DoctorCode
GROUP BY PatientCode, Patient
于 2014-11-30T06:00:05.313 回答