如何根据字段值将查询结果转换为其他列

Posted

技术标签:

【中文标题】如何根据字段值将查询结果转换为其他列【英文标题】:How to pivot query result into additional columns based on a field value 【发布时间】:2021-04-20 19:11:40 【问题描述】:

因此,我可以了解装配所需的库存位置和组件数量。 我想在两个位置获取 BINS 和 Quantities,并且我想为每个组件并排列出它们。 这是我最近的尝试:

DECLARE @INVMTL TABLE(
                  [COMPONENT]    VARCHAR(50), 
                  [LOCATION]     VARCHAR(50), 
                  [BIN]          VARCHAR(50), 
                  [QTY]          VARCHAR(50))

DECLARE @FGMTL TABLE(
                 [COMPONENT]    VARCHAR(50), 
                 [LOCATION]     VARCHAR(50), 
                 [BIN]          VARCHAR(50), 
                 [QTY]          VARCHAR(50))

INSERT INTO @INVMTL
SELECT [COMPONENT]
     , [LOCATION]
     , [BIN]
     , [QTY]
FROM vw_WorkOrdersKitLoc AS INVMTL
WHERE [INVMTL].[LOCATION] = 'INVMTL'
      AND [INVMTL].[ITEMNO] = 'ASSEMBLYNAME'

INSERT INTO @FGMTL
SELECT [COMPONENT]
     , [LOCATION]
     , [BIN]
     , [QTY]
FROM vw_WorkOrdersKitLoc AS FGMTL
WHERE [FGMTL].[LOCATION] = 'FGMTL'
     AND [FGMTL].[ITEMNO] = 'ASSEMBLYNAME'

SELECT  COALESCE([INVMTL].[COMPONENT], [FGMTL].[COMPONENT])
     , [INVMTL].[LOCATION]
     , [INVMTL].[BIN]
     , [INVMTL].[QTY]
     , [FGMTL].[LOCATION]
     , [FGMTL].[BIN]
     , [FGMTL].[QTY]
FROM @INVMTL AS INVMTL
     LEFT OUTER JOIN @FGMTL AS FGMTL ON FGMTL.COMPONENT = INVMTL.COMPONENT

This is what it returns. As you can see the extra right columns have duplicated data where it should be null. 我也知道有一种更短、更简洁的方法,我只是忘记了。

Here is the view returning all the data I want to reorganize

I made a spreadsheet of how I would like the retrieve this data

感谢您的帮助

【问题讨论】:

请将展品以文本形式粘贴到问题中。 【参考方案1】:

您的连接不够具体-您只需要求数据库将此处的该组件与那里的该组件匹配,这意味着一侧的一个ABC,1 组件,位置将与一个ABC,2 1:1 匹配另一个给ABC,1,ABC,2,但如果你只匹配每个的组件(ABC),一侧的两个ABC和另一侧的3将最终相乘(笛卡尔爆炸)变为6:

(ABC,1 and ABC,2) join (ABC,3 and ABC,4 and ABC,5)
gives:
ABC,1,ABC,3
ABC,1,ABC,4
ABC,1,ABC,5
ABC,2,ABC,3
ABC,2,ABC,4
ABC,2,ABC,5

要查看您的电子表格应用了哪些匹配逻辑并不容易。看起来 LOC 是按 alpha 升序排序的,然后第 1 行与第 1 行匹配,第 2 行与第 2 行匹配,等等。您需要提供一个假键才能加入:

DECLARE @INVMTL TABLE(
                  [COMPONENT]    VARCHAR(50), 
                  [LOCATION]     VARCHAR(50), 
                  [BIN]          VARCHAR(50), 
                  [QTY]          VARCHAR(50),
                  fakekey INT)

DECLARE @FGMTL TABLE(
                 [COMPONENT]    VARCHAR(50), 
                 [LOCATION]     VARCHAR(50), 
                 [BIN]          VARCHAR(50), 
                 [QTY]          VARCHAR(50),
                 fakekey INT)

INSERT INTO @INVMTL
SELECT [COMPONENT]
     , [LOCATION]
     , [BIN]
     , [QTY]
     , row_number() over(partition by COMPONENT order by location) as fakekey
FROM vw_WorkOrdersKitLoc AS INVMTL
WHERE [INVMTL].[LOCATION] = 'INVMTL'
      AND [INVMTL].[ITEMNO] = 'ASSEMBLYNAME'

INSERT INTO @FGMTL
SELECT [COMPONENT]
     , [LOCATION]
     , [BIN]
     , [QTY]
     , row_number() over(partition by COMPONENT order by location) as fakekey
FROM vw_WorkOrdersKitLoc AS FGMTL
WHERE [FGMTL].[LOCATION] = 'FGMTL'
     AND [FGMTL].[ITEMNO] = 'ASSEMBLYNAME'

SELECT  COALESCE([INVMTL].[COMPONENT], [FGMTL].[COMPONENT])
     , [INVMTL].[LOCATION]
     , [INVMTL].[BIN]
     , [INVMTL].[QTY]
     , [FGMTL].[LOCATION]
     , [FGMTL].[BIN]
     , [FGMTL].[QTY]
FROM @INVMTL AS INVMTL
     FULL OUTER JOIN @FGMTL AS FGMTL ON FGMTL.COMPONENT = INVMTL.COMPONENT and fgmtl.fakekey = invmtl.fakekey

对于更短的方式,您可以使用 WITH:

WITH INVMTL as (
  SELECT [COMPONENT]
     , [LOCATION]
     , [BIN]
     , [QTY]
     , row_number() over(partition by COMPONENT order by location) as fakekey
  FROM vw_WorkOrdersKitLoc AS INVMTL
  WHERE [INVMTL].[LOCATION] = 'INVMTL'
      AND [INVMTL].[ITEMNO] = 'ASSEMBLYNAME'
), FGMTL as (
  SELECT [COMPONENT]
     , [LOCATION]
     , [BIN]
     , [QTY]
     , row_number() over(partition by COMPONENT order by location) as fakekey
  FROM vw_WorkOrdersKitLoc AS FGMTL
  WHERE [FGMTL].[LOCATION] = 'FGMTL'
     AND [FGMTL].[ITEMNO] = 'ASSEMBLYNAME'
)
SELECT  COALESCE([INVMTL].[COMPONENT], [FGMTL].[COMPONENT])
     , [INVMTL].[LOCATION]
     , [INVMTL].[BIN]
     , [INVMTL].[QTY]
     , [FGMTL].[LOCATION]
     , [FGMTL].[BIN]
     , [FGMTL].[QTY]
FROM 
    INVMTL
    FULL OUTER JOIN FGMTL 
    ON 
      FGMTL.COMPONENT = INVMTL.COMPONENT and 
      fgmtl.fakekey = invmtl.fakekey

或者为 FGMTL 等定义视图。

【讨论】:

感谢您的帮助。那成功了。有趣的是,在阅读您的答案之前,我只是想在几分钟内使用带有行号的假键。我想我需要退后一步。也感谢你提醒我使用“With”而不是创建临时变量表​​!!

以上是关于如何根据字段值将查询结果转换为其他列的主要内容,如果未能解决你的问题,请参考以下文章

根据列值将 SQL 结果组合成组

根据字段值聚合数据

sqlite - 根据字段值将 2 行中的相同字段组合成 2 列

根据公共列值将定义的行数转换为列

如何查询行中是不是存在值将值添加到另一个字段?

如何展平 SQL 查询的结果 - 将行转换为列?