【问题标题】:Combine SQL select data-set multiple rows into a single row based on column values根据列值将SQL select数据集多行合并为一行
【发布时间】:2018-06-13 16:26:35
【问题描述】:

我有一个 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 值,并且我根据序列。

一些“序列”具有对应于所有 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

【问题讨论】:

  • 您的报告工具可能已经具有用于交叉表或数据透视报告的内置功能。您可以直接使用它,而无需对查询进行任何修改。试试看是否有效

标签: sql sql-server database relational-database


【解决方案1】:

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

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

如果失败,您可以使用 CTE 破解它 Concatenation with CTEs

【讨论】:

    【解决方案2】:

    你可以试试这个吗?

        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
    

    【讨论】:

    • 试过但没用。不过会更接近您的查询
    【解决方案3】:

    试试这个查询:

    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
    

    【讨论】:

      猜你喜欢
      • 2022-01-13
      • 2016-04-27
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-11
      相关资源
      最近更新 更多