根据列值将SQL select数据集多行组合成一行

时间:2018-01-03 23:53:31

标签: sql sql-server database relational-database

我有一个SQL查询,而不是将来自多个数据库表的数据合并到一个数据集中,如:

SELECT 
    CS.Id As ID,
    CP.Country As Country,
    S.Title As Site,
    CONCAT(V.Title,' ',M.Model,' ',M.Version) As Machine,
    CP.Title As Protocol,
    CS.Title As Sequence,
    IQS.SequenceType AS Type,
    IQS.ImageQuality AS IQ,
    _IQBeforeOpt =
        CASE IQS.SequenceType
            WHEN 1 THEN IQS.ImageQuality
        END,
    _IQDuringOpt = 
        CASE IQS.SequenceType
            WHEN 2 THEN IQS.ImageQuality
        END,
    _IQAfterOpt = 
        CASE IQS.SequenceType
            WHEN 3 THEN IQS.ImageQuality
        END,
   ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY))) AS SeqPI,
   _SeqPIBeforeOpt = 
        CASE IQS.SequenceType
            WHEN 1 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
       END,
  _SeqPIDuringOpt =
      CASE IQS.SequenceType
          WHEN 2 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
      END,
  _SeqPIAfterOpt =
      CASE IQS.SequenceType
          WHEN 3 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
      END       
FROM ClientSequence CS
JOIN ImageQualitySequencePool IQS ON CS.Id = IQS.SequenceId
JOIN ClientProtocol CP ON CS.ClientProtocolId = CP.Id
JOIN Team S ON CP.TeamID = S.Id
JOIN Machine M On CP.MachineId = M.Id
JOIN Vendor V ON M.VendorId = V.Id
ORDER BY CP.Country,S.Title,CP.MachineId,CP.Title,CS.Title,IQS.SequenceType

上面的查询用于组合来自多个表的数据(主表是ClientSequence& ImageQualitySequencePool),以构建我想用于报表的数据集。

以下是一些指示性值:

ID  Country    Site    Machine   Protocol   Sequence          Type  IQ   _IQBeforeOpt   _IQDuringOpt   _IQAfterOpt  SeqPI   _SeqPIBeforeOpt   _SeqPIDuringOpt    _SeqPIAfterOpt
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
41  Country_1  Site_1  Mach_1    ProtocolA  Ax_PD_FSE_FS      1     2    2              NULL            NULL         0.805   0.805             NULL               NULL
86  Country_1  Site_1  Mach_1    ProtocolA  Ax_PD_FSE_FS      2     4    NULL           4               NULL         1.38    NULL              1.38               NULL
91  Country_1  Site_1  Mach_1    ProtocolA  Ax_PD_FSE_FS      3     3    NULL           NULL            3            1.03    NULL              NULL               1.03

76  Country_1  Site_1  Mach_1    ProtocolB  Cor_PD_FSE_FS     1     3    3              NULL            NULL         0.83    0.83              NULL               NULL
88  Country_1  Site_1  Mach_1    ProtocolB  Cor_PD_FSE_FS     2     4    NULL           4               NULL         1.62    NULL              1.62               NULL
92  Country_1  Site_1  Mach_1    ProtocolB  Cor_PD_FSE_FS     3     3    NULL           NULL            3            1.21    NULL              NULL               1.21

91  Country_2  Site_3  Mach_3    ProtocolA  Seg_SF_FSE_FS     1     3    1              NULL            NULL         1.41    1.41              NULL               NULL
94  Country_2  Site_3  Mach_3    ProtocolA  Seg_SF_FSE_FS     2     2    NULL           2               NULL         1.28    NULL              1.28               NULL

72  Country_2  Site_3  Mach_3    ProtocolC  Ger_SE_FSE_FS     1     3    3              NULL            NULL         0.83    0.83              NULL               NULL

因此,“国家,地点,机器,协议,序列”的每个组合可以是类型:1,2或3意义:

  • 类型1:优化前的序列
  • 类型2:序列期间 优化
  • 类型3:优化后的序列

正如你在查询中看到的那样,我有一些IQ&值; SeqPI存储在数据库中,我根据序列的类型动态填充字段(_IQBeforeOpt,_IQDuringOpt,_IQAfterOpt)和(_SeqPIBeforeOpt,_SeqPIDuringOpt,_SeqPIAfterOpt)。

某些“序列”的记录对应于所有3种类型,而另一些则不具有。

我想要的是将“国家,网站,机器,协议,序列”的特定组合的所有记录合并为一行。所以最后我想得到一个产生如下数据集的查询:

Country    Site    Machine   Protocol    Sequence       Type     _IQBeforeOpt   _IQDuringOpt   _IQAfterOpt  _SeqPIBeforeOpt   _SeqPIDuringOpt    _SeqPIAfterOpt
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Country_1  Site_1  Mach_1    ProtocolA   Ax_PD_FSE_FS   1,2,3    2              4             3            0.805              1.38               1.03
Country_1  Site_1  Mach_1    ProtocolB   Cor_PD_FSE_FS  1,2,3    3              4             3            0.83               1.62               1.21
Country_2  Site_3  Mach_3    ProtocolA   Seg_SF_FSE_FS  1,2      3              2             NULL         1.41               1.28               NULL
Country_2  Site_3  Mach_3    ProtocolC   Ger_SE_FSE_FS  1        3              NULL          NULL         0.83               NULL               NULL

3 个答案:

答案 0 :(得分:2)

尝试此查询:

SELECT
    CP.Country As Country,
    S.Title As Site,
    CONCAT(V.Title,' ',M.Model,' ',M.Version) As Machine,
    CP.Title As Protocol,
    CS.Title As Sequence,
    STUFF(CONCAT(MAX(IIF(IQS.SequenceType = 1, ',1', '')), MAX(IIF(IQS.SequenceType = 2, ',2', '')), MAX(IIF(IQS.SequenceType = 3, ',3', ''))),1,1,'') AS Type,
    _IQBeforeOpt =
        MAX(CASE IQS.SequenceType
            WHEN 1 THEN IQS.ImageQuality
        END),
    _IQDuringOpt = 
        MAX(CASE IQS.SequenceType
            WHEN 2 THEN IQS.ImageQuality
        END),
    _IQAfterOpt = 
        MAX(CASE IQS.SequenceType
            WHEN 3 THEN IQS.ImageQuality
        END),
   _SeqPIBeforeOpt = 
        MAX(CASE IQS.SequenceType
            WHEN 1 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
       END),
  _SeqPIDuringOpt =
      MAX(CASE IQS.SequenceType
          WHEN 2 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
      END),
  _SeqPIAfterOpt =
      MAX(CASE IQS.SequenceType
          WHEN 3 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
      END)      
FROM 
    ClientSequence CS
    JOIN ImageQualitySequencePool IQS ON CS.Id = IQS.SequenceId
    JOIN ClientProtocol CP ON CS.ClientProtocolId = CP.Id
    JOIN Team S ON CP.TeamID = S.Id
    JOIN Machine M On CP.MachineId = M.Id
    JOIN Vendor V ON M.VendorId = V.Id
GROUP BY CP.Country, S.Title, CONCAT(V.Title,' ',M.Model,' ',M.Version), CP.Title, CS.Title

答案 1 :(得分:0)

窗口函数是一种有效的聚合方式: Over Clause

使用OVER子句,您可以定义自己的聚合函数。

如果失败,你可以用CTE攻击它 Concatenation with CTEs

答案 2 :(得分:0)

你能试试吗?

    SELECT 
    CS.Id As ID,
    CP.Country As Country,
    S.Title As Site,
    CONCAT(V.Title,' ',M.Model,' ',M.Version) As Machine,
    CP.Title As Protocol,
    CS.Title As Sequence,
 --   IQS.SequenceType AS Type,
    STUFF(OQS.types,1,1,'') AS [type],
  --  IQS.ImageQuality AS IQ,
    _IQBeforeOpt =MAX(
        CASE IQS.SequenceType
            WHEN 1 THEN IQS.ImageQuality
        END),
    _IQDuringOpt =MAX( 
        CASE IQS.SequenceType
            WHEN 2 THEN IQS.ImageQuality
        END),
    _IQAfterOpt = 
        MAX(CASE IQS.SequenceType
            WHEN 3 THEN IQS.ImageQuality
        END),
 --  ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY))) AS SeqPI,
   _SeqPIBeforeOpt = MAX(
        CASE IQS.SequenceType
            WHEN 1 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
       END),
  _SeqPIDuringOpt =MAX(
      CASE IQS.SequenceType
          WHEN 2 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
      END),
  _SeqPIAfterOpt =MAX(
      CASE IQS.SequenceType
          WHEN 3 THEN ((IQS.ImageQuality*IQS.SeqSlices)/(IQS.SeqTime*(CS.slicetkndef*CS.pixelspacingX*CS.pixelspacingY)))
      END)       
FROM ClientSequence CS
JOIN ImageQualitySequencePool IQS ON CS.Id = IQS.SequenceId
JOIN ClientProtocol CP ON CS.ClientProtocolId = CP.Id
JOIN Team S ON CP.TeamID = S.Id
JOIN Machine M On CP.MachineId = M.Id
JOIN Vendor V ON M.VendorId = V.Id
OUTER APPLY(SELECT ','+LTRIM(QS.SequenceType) FROM ImageQualitySequencePool AS QS WHERE CS.Id = QS.SequenceId FOR XML PATH('')) OQS(types)
GROUP BY CS.Id, CP.Country, S.Title ,CONCAT(V.Title,' ',M.Model,' ',M.Version),CP.MachineId,CP.Title,CS.Title,oQS.types
ORDER BY CP.Country,S.Title,CP.MachineId,CP.Title,CS.Title--,IQS.SequenceType