我正在尝试透视数据。我们从两列开始:ListNum和Value
该行是“诚信”吗?没关系,我只希望所有值向上折叠并删除空值。
在这种情况下,ListNum类似于枚举,其值限制为List1,List2或List3。请注意,它们不按顺序排列(1、3、3、1,2,而不是1,2,3,1,2,3等)。
最好有一个使用标准sql的解决方案,以便它可以在许多数据库中工作。
起点:
+---------+------------+
| ListNum | Value |
+---------+------------+
| List1 | A |
| List3 | 123 |
| List3 | CDE |
| List1 | Somestring |
| List2 | randString |
+---------+------------+
我能够使用以下方法将列表分为几列:
select
case when ListNum = "List1" then Value end as List1,
case when ListNum = "List2" then Value end as List2,
case when ListNum = "List3" then Value end as List3
from Table;
中点:
+------------+------------+-------+
| List1 | List2 | List3 |
+------------+------------+-------+
| A | NULL | NULL |
| NULL | NULL | 123 |
| NULL | NULL | CDE |
| Somestring | NULL | NULL |
| NULL | randString | NULL |
+------------+------------+-------+
但是现在我需要向上折叠/删除null以获得- 所需的输出:
+------------+------------+-------+
| List1 | List2 | List3 |
+------------+------------+-------+
| A | randString | 123 |
| Somestring | NULL | CDE |
+------------+------------+-------+
答案 0 :(得分:2)
您是否缺少某种分组标准?您如何确定A
属于123
而不属于CDE
?为什么randString
在第一行而不是第二行?
使用这样的分组键很容易:
DECLARE @tbl TABLE(GroupingKey INT, ListNum VARCHAR(100),[Value] VARCHAR(100));
INSERT INTO @tbl VALUES
(1,'List1','A')
,(1,'List3','123')
,(2,'List3','CDE')
,(2,'List1','Somestring')
,(1,'List2','randString');
SELECT p.*
FROM @tbl
PIVOT
(
MAX([Value]) FOR ListNum IN(List1,List2,List3)
) p;
但是对于您的数据,这似乎是随机的...
以下方法会将值随机地排序到其列中:
DECLARE @tbl TABLE(ListNum VARCHAR(100),[Value] VARCHAR(100));
INSERT INTO @tbl VALUES
('List1','A')
,('List3','123')
,('List3','CDE')
,('List1','Somestring')
,('List2','randString');
-这将使用三个独立但编号的集合并将它们加入:
WITH All1 AS (SELECT [Value],ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RandomNumber FROM @tbl WHERE ListNum='List1')
,All2 AS (SELECT [Value],ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RandomNumber FROM @tbl WHERE ListNum='List2')
,All3 AS (SELECT [Value],ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RandomNumber FROM @tbl WHERE ListNum='List3')
SELECT All1.[Value] AS List1
,All2.[Value] AS List2
,All3.[Value] AS List3
FROM All1
FULL OUTER JOIN All2 ON All1.RandomNumber=All2.RandomNumber
FULL OUTER JOIN All3 ON All1.RandomNumber=All3.RandomNumber ;
根据您的评论:
这只是索引/实例号。 randString是第一个非空行。
没有特定的ORDER BY
,相同的SELECT
可能会以任何随机顺序返回您的数据。因此,没有第一非空行,至少没有 first的意思在第二 ...
答案 1 :(得分:1)
使用递归CTE的方法可能会起作用:
DECLARE @tbl TABLE( ListNum VARCHAR(100),[Value] VARCHAR(100));
INSERT INTO @tbl VALUES
( 'List1','A')
,( 'List3','123')
,( 'List3','CDE')
,( 'List1','Somestring')
,( 'List2','randString');
DECLARE @mmax int;
SELECT @mmax = cnt from (SELECT TOP 1 count(*) cnt from @tbl group by ListNum ORDER BY count(*) DESC) t;
With rec AS (
SELECT 1 AS num
UNION ALL
SELECT num+1 FROM rec WHERE num+1<=@mmax
)
SELECT t1.List1, t2.List2, t3.List3 FROM rec
FULL JOIN (
select Value as List1, row_number() over(order by ListNum) rn from @tbl where ListNum = 'List1'
) t1
ON rec.num = t1.rn
FULL JOIN
(
select Value as List2, row_number() over(order by ListNum) rn from @tbl where ListNum = 'List2'
) t2
ON rec.num = t2.rn
FULL JOIN
(
select Value as List3, row_number() over(order by ListNum) rn from @tbl where ListNum = 'List3'
) t3
ON rec.num = t3.rn;
答案 2 :(得分:0)
通常,您会使用诸如MAX之类的汇总操作,因为它会隐藏null(除非组中没有其他有效值,否则null永远不会是max)。但是您的查询有点奇怪,因为您没有似乎没有一个可靠的枢轴锚点,并且您正在允许您的任何数据与其他任何内容关联。在现实世界中,这可能不会发生,因为它不是特别有用
更好的示例数据:
Person, Attribute, Value
1, Name, John
1, Age, 10
2, Name, Sarah
3 Age, 39
透视查询:
SELECT
Person,
MAX(case when attribute = 'name' then value end) as name,
MAX(case when attribute = 'age' then value end) as age
FROM
data
GROUP BY person
结果:
Person, Name, Age
1, John, 10
2, Sarah, NULL
3, NULL, 39