2014-11-30 1 views
0

У меня есть совместная таблица из трех разных таблиц.Как сгруппировать несколько строк из нескольких столбцов в объединенной таблице с группировкой по 1 столбцу

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 ('') для группировки каждого столбца будет очень медленно. Итак, как я могу эффективно группировать эту таблицу?

ответ

1

Я думаю, что ответ использует функцию агрегации, которая объединяет строки в группе. Жаль TSQL не один (? Как трудно это), но если вы не возражаете против использования SQLCLR, вот как создать определенный пользователем агрегатную функцию конкатенации с .NET в MSDN:

MSDN String Utility Functions Sample

<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