SQL:按列单元格将列拆分为多个列

时间:2016-07-25 21:32:52

标签: sql sql-server vba

我试图在VBA中构建一个模块,该模块将查询2个数据源并将它们连接到" Name"的公共字段上。问题是数据的粒度不同。我试图改变的集合目前看起来像这样:

current

我试图让它看起来像这样:

desired

这样我就可以使用来自我的第二个数据集的查询加入它,该数据集由" name"而不是"项目值"。

FWIW,这是我目前正在尝试运行的查询的样子。我使用隐式连接来获得"当前值"和过去的价值"对于每个" name",但这些都不是指数据集2:

with set1 as (SELECT NAME, ITEM_CODE, ITEM_VALUE_NUMBER as CURRENT_VALUE FROM [...] WHERE [...]),
with set2 as (SELECT NAME, ITEM_CODE, ITEM_VALUE_NUMBER as PAST_VALUE FROM [...] WHERE [...]),
SELECT set1.NAME [ITEM_1], [ITEM_2], [ITEM_3] from
(SELECT set1.NAME, set1.CURRENT_VALUE, set2.PAST_VALUE FROM set1, set2 WHERE set1.NAME=set2.NAME and set1.ITEM_CODE=set2.ITEM_CODE) AS SourceTable
PIVOT (max(CURRENT_VALUE) for ITEM_CODE in [ITEM_1], [ITEM_2], [ITEM_3]) AS PivotTable;

提前感谢您提供的任何指导!

1 个答案:

答案 0 :(得分:1)

所以,你有几个选择。首先是尝试重新调整数据枢轴以获得所需的结果,这使得查询比所需的更复杂。如果您愿意,可以通过以下方式执行此操作:

SELECT Name
     , MAX(C1) Item1CurrentValue
     , MAX(P1) Item1PastValue
     , MAX(C2) Item2CurrentValue
     , MAX(P2) Item2PastValue
     , MAX(C3) Item3CurrentValue
     , MAX(P3) Item3PastValue
FROM (
    SELECT set1.Name
         , 'C' + CAST(set1.ItemCode AS VARCHAR(255)) ItemCode1
         , CurVal
         , 'P' + CAST(set2.ItemCode AS VARCHAR(255)) ItemCode2
         , PastVal
    FROM (SELECT Name, ItemCode, ITEM_VALUE_NUMBER CurVal FROM myFirstQuery) set1
    JOIN (SELECT Name, ItemCode, ITEM_VALUE_NUMBER PastVal FROM mySecondQuery) set2 ON set1.Name = set2.Name AND set1.ItemCode = set2.ItemCode) T
PIVOT (MAX(CurVal) FOR ItemCode1 IN (C1, C2, C3)) P1
PIVOT (MAX(PastVal) FOR ItemCode2 IN (P1, P2, P3)) P2
GROUP BY Name;

我真的不认为CTE使查询更具可读性,所以我只是删除了它们,但如果你愿意,你可以以类似的方式使用CTE。

更好(也更容易理解,在我看来)的方式是使用条件聚合,如:

SELECT Name
     , MAX(CASE WHEN ItemCode = 1 THEN CurVal END) Item1CurrentValue
     , MAX(CASE WHEN ItemCode = 1 THEN PastVal END) Item1PastValue
     , MAX(CASE WHEN ItemCode = 2 THEN CurVal END) Item2CurrentValue
     , MAX(CASE WHEN ItemCode = 2 THEN PastVal END) Item2PastValue
     , MAX(CASE WHEN ItemCode = 3 THEN CurVal END) Item3CurrentValue
     , MAX(CASE WHEN ItemCode = 3 THEN PastVal END) Item3PastValue
FROM (
    SELECT set1.Name
         , set1.ItemCode
         , CurVal
         , PastVal
    FROM (SELECT Name, ItemCode, ITEM_VALUE_NUMBER CurVal FROM myFirstQuery) set1
    JOIN (SELECT Name, ItemCode, ITEM_VALUE_NUMBER PastVal FROM mySecondQuery) set2 ON set1.Name = set2.Name AND set1.ItemCode = set2.ItemCode) T
GROUP BY Name;