一行中有一对多的SQL

时间:2013-11-26 11:36:26

标签: sql sql-server sql-server-2005 pivot

我有一张表,记录每次出勤的患者诊断。患者可以有多个诊断。

我希望每次出勤都有一排进行所有诊断(最多12次诊断)。下面会回来一行。

select
    dg.AttendanceID
    , dg.PatientNumber
    , dg.DiagnosisDate
    , dg.Diagnosis
from
    Diagnosis dg


AttendanceID    PatientNumber   DiagnosisDate   Diagnosis
10001           123456          01-Oct-13   A
10001           123456          01-Oct-13   B
10002           123456          20-Oct-13   D

结果应如下所示:

AttendanceID    PatientNumber   DiagnosisDate   Diagnosis 1 Diagnosis 2 Diagnosis 3
10001           123456          01-Oct-13   A            B       
10002           123456          20-Oct-13   D   

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:2)

您可以通过实施PIVOT功能获得结果,但我还建议使用窗口函数row_number()来生成每个attendanceidpatientnumber的诊断数量:

select attendanceid, patientnumber,
  diagnosisdate,
  Diagnosis1, Diagnosis2, Diagnosis3
from
(
  select attendanceid, patientnumber,
    diagnosisdate, diagnosis,
    'diagnosis'+
      cast(row_number() over(partition by attendanceid, patientnumber
                              order by diagnosis) as varchar(2)) seq
  from diagnosis
) d
pivot
(
  max(diagnosis)
  for seq in (Diagnosis1, Diagnosis2, Diagnosis3)
) piv;

SQL Fiddle with Demo。由于您知道每位患者/出勤者最多可以进行12次诊断,因此您可以轻松地对查询进行硬编码以添加其他列。

但是如果您需要动态版本的代码,那么您可以使用类似于以下内容的内容:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(seq) 
                    from
                    (
                       select 'diagnosis'+
                          cast(row_number() over(partition by attendanceid, patientnumber
                               order by diagnosis) as varchar(2)) seq
                       from diagnosis
                    ) d
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT attendanceid, patientnumber,
               diagnosisdate,' + @cols + ' 
            from 
            (
              select attendanceid, patientnumber,
                diagnosisdate, diagnosis,
                ''diagnosis''+
                  cast(row_number() over(partition by attendanceid, patientnumber
                                          order by diagnosis) as varchar(2)) seq
              from diagnosis
            ) x
            pivot 
            (
                max(diagnosis)
                for seq in (' + @cols + ')
            ) p '

execute sp_executesql @query;

请参阅SQL Fiddle with Demo

两个版本都给出了结果:

| ATTENDANCEID | PATIENTNUMBER |                  DIAGNOSISDATE | DIAGNOSIS1 | DIAGNOSIS2 | DIAGNOSIS3 |
|--------------|---------------|--------------------------------|------------|------------|------------|
|        10001 |        123456 | October, 01 2013 00:00:00+0000 |          A |          B |     (null) |
|        10002 |        123456 | October, 20 2013 00:00:00+0000 |          D |     (null) |     (null) |

答案 1 :(得分:0)

我不是百分百肯定,但它应该是这样的。

;with cte as(
select
dg.AttendanceID
, dg.PatientNumber
, dg.DiagnosisDate
, dg.Diagnosis
,ROW_NUMBER() over (partition by dg.attendanceID order by attendanceID) as seq1
,ROW_NUMBER() over (partition by dg.attendanceID, patient_no order by diagnosis) as seq2
from
Diagnosis dg
)

 select
 t1.attendanceID
 ,t1.patientNumber
 ,t1.diagnosisDate
 ,(select Diagnosis from cte t2 where t1.attendanceID=t2.attendanceID and             t1.patientNumber=t2.patientNumber and t2.seq2='1') as diag1
 ,(select Diagnosis from cte t2 where t1.attendanceID=t2.attendanceID and    t1.patientNumber=t2.patientNumber and t2.seq2='2') as diag2
 ,(select Diagnosis from cte t2 where t1.attendanceID=t2.attendanceID and t1.patientNumber=t2.patientNumber and t2.seq2='3') as diag3
 ,(select Diagnosis from cte t2 where t1.attendanceID=t2.attendanceID and t1.patientNumber=t2.patientNumber and t2.seq2='4') as diag4
 ,(select Diagnosis from cte t2 where t1.attendanceID=t2.attendanceID and t1.patientNumber=t2.patientNumber and t2.seq2='5') as diag5
  from cte t1
  where seq1= 1

答案 2 :(得分:0)

以下是使用游标的可能解决方案我不确定您是否可以将其显示为列,因为它对于每个患者都是可变的但是这将在单个列中显示为逗号分隔的诊断

DECLARE @combinedString VARCHAR(MAX),
@id int,
@Diagnosis VARCHAR(MAX)


Declare @CONCATRESULT TABLE (AttendanceID int, Question VARCHAR(MAX) )

Declare Dia cursor for 
SELECT  AttendanceID FROM  Diagnosis 

open Dia 
Fetch next from Dia into @id
while @@FETCH_STATUS=0 
begin

SELECT   @combinedString = COALESCE(@combinedString + ', ', '') + Diagnosis,         
@id=AttendanceID  FROM [Prod_PostData].[dbo].[KMSFPostDataDenorm] d
WHERE AttendanceID = @id

insert into @CONCATRESULT values (  @id ,@combinedString )

SET @combinedString = null

Fetch next from Dia into @id
end
close Dia
deallocate Dia


select
dg.AttendanceID
, dg.PatientNumber
, dg.DiagnosisDate
, dg.Diagnosis
from
Diagnosis dg join (select * from @CONCATRESULT) Y on dg.AttendanceID=Y.AttendanceID