如何将两行变成两列

时间:2019-02-28 22:01:03

标签: sql sql-server

我有以下SQL查询:

select
    distinct

    Equipment_Reserved.Equipment_Attached_To,
    Equipment.Name
from
    Equipment,
    Studies,
    Equipment_Reserved
where
    Studies.Study = 'MAINT19-01'
    and
    Equipment.idEquipment = Equipment_Reserved.Equipment_idEquipment
    and
    Studies.idStudies = Equipment_Reserved.Studies_idStudies
    and
    Equipment.Type = 'Probe'

此查询产生以下结果:

Equipment_Attached_To   Name
2297                    R1-P1
2297                    R1-P2
2299                    R1-P3

我想将其更改为以下内容:

Equipment_Attached_To   Name1     Name2
2297                    R1-P1     R1-P2
2299                    R1-P3     NULL

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

我首先将您的查询从旧的,旧的JOIN语法更改为显式联接,因为它使查询更易于理解:

def test_1(self, mock1, mock2, mockn):
  default_setup(mock1, mock2, mockn)
  # further test code...

def test_2(self, mock1, mock2, mockn):
  default_setup(mock1, mock2, mockn)
  setup_mock2_to_behave_as_xxx(mock2)
  # further test code...

def test_3(self, mock1, mock2, mockn):
  setup_mock1_to_always_xxx(mock1)
  setup_mock2_to_behave_as_xxx(mock2)
  setup_mockn_to_xxx(mockn)
  # further test code...

我认为您实际上不需要SELECT DISTINCT Equipment_Reserved.Equipment_Attached_To, Equipment.Name FROM Equipment INNER JOIN Equipment_Reserved ON Equipment_Reserved.Equipment_idEquipment = Equipment.idEquipment INNER JOIN Studies ON Studies.idStudies = Equipment_Reserved.Studies_idStudies WHERE Studies.Study = 'MAINT19-01' AND Equipment.Type = 'Probe' -我认为您可以使用PIVOT函数通过嵌套查询来完成此操作。我已经看到,ROW_NUMBER查询通常比嵌套查询的查询执行计划更糟糕。

让我们在整个查询中添加PIVOT(由于它是窗口功能,因此需要ROW_NUMBER)和整个查询中的匹配ORDER BY,以使其一致。我们还使用ORDER BY,以便为每个PARTITION BY值重置行号:

Equipment_Attached_To

这将给出如下输出:

SELECT
    DISTINCT
    Equipment_Reserved.Equipment_Attached_To,
    Equipment.Name,

    ROW_NUMBER() OVER (PARTITION BY Equipment_Attached_To ORDER BY [Name]) AS RowNumber

FROM
    Equipment
    INNER JOIN Equipment_Reserved ON Equipment_Reserved.Equipment_idEquipment = Equipment.idEquipment
    INNER JOIN Studies            ON Studies.idStudies = Equipment_Reserved.Studies_idStudies

WHERE
    Studies.Study = 'MAINT19-01'
    AND
    Equipment.Type = 'Probe'

ORDER BY
    Equipment_Attached_To,
    [Name]

然后可以将其拆分为显式列,如下所示。 Equipment_Attached_To Name RowNumber 2297 R1-P1 1 2297 R1-P2 2 2299 R1-P3 1 的使用是任意的(我们可以使用MAX()),这仅是因为我们正在处理MIN(),并且因为GROUP BY将输入集限制为1还是排。

CASE WHEN...

所以最后一个查询是:

SELECT
    Equipment_Attached_To,
    MAX( CASE WHEN RowNumber = 1 THEN [Name] END ) AS Name1,
    MAX( CASE WHEN RowNumber = 2 THEN [Name] END ) AS Name2
FROM
    (
        -- the query from above
    )
GROUP BY
    Equipment_Attached_To
ORDER BY
    Equipment_Attached_To,
    Name1,
    Name2

答案 1 :(得分:0)

让我们从一些基础知识开始。

  • 为了便于阅读代码,我使用表的缩写为表添加了别名。
  • 然后,我转换了旧的连接语法,自1992年以来已经过时,部分使用了标准语法(27年以来,人们仍然使用旧的语法)。
  • 最后,由于只有两个可能的值,我们可以使用MINMAX将它们分成两列。
  • 由于我们正在使用聚合函数,因此我们删除了DISTINCT并使用了GROUP BY 现在的代码如下所示:

    SELECT er.Equipment_Attached_To, 
        --Gets the first row for the id
        MIN( e.Name) AS Name1, 
        --If the MAX is equal to the MIN, returns a NULL. If not, it returns the second value.
        NULLIF( MAX(e.Name), MIN( e.Name)) AS Name2 
    FROM Equipment e
    JOIN Studies s ON s.idStudies = er.Studies_idStudies
    JOIN Equipment_Reserved er ON e.idEquipment = er.Equipment_idEquipment
    WHERE s.Study = 'MAINT19-01'
    AND e.Type = 'Probe'
    GROUP BY er.Equipment_Attached_To;