Sql server 如何在按1列分组的联接表中对多行多列进行分组
我有一张三张不同桌子的联合桌,像这样Sql server 如何在按1列分组的联接表中对多行多列进行分组,sql-server,group-by,for-xml-path,Sql Server,Group By,For Xml Path,我有一张三张不同桌子的联合桌,像这样 Select DoctorTable.Doctor, NurseTable.Nurse , PatientTable.Patents FROM PatientTable LEFT JOIN DoctorTable on DoctorTable.DoctorCode = PatientTable.DoctorCode LEFT JOIN NurseTable on DoctorTable.DoctorCode = NurseTable.DoctorCo
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(“”)对每个列进行分组将非常缓慢。那么我如何才能有效地对这个表进行分组呢?我认为答案是使用一个聚合函数来连接组中的行。太糟糕了,TSQL没有一个聚合连接函数(这有多困难?),但是如果您不介意使用SQLCLR,下面介绍如何在MSDN中使用.NET创建用户定义的聚合连接函数:
<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