我有一个数据透视表,可以将垂直数据库设计转换为水平数据库设计:
源表:
Id ParentId Property Value
---------------------------------
1 1 Date 01-09-2015
2 1 CountValue 2
3 1 TypeA Value1
4 1 TypeB Value2
5 1 TypeC Value2
6 2 Date 15-10-2015
7 2 CountValue 3
8 2 TypeA Value3
9 2 TypeB Value22
10 2 TypeC Value99
旋转后,这看起来像:
ParentId Date CountValue TypeA TypeB TypeC
----------------------------------------------------------
1 01-09-2015 2 Value1 Value2 Value2
2 15-10-2015 3 Value3 Value22 Value99
然后,在TypeA
,TypeB
和TypeC
列中有一个有效值的查找表:
Id Name Value
-----------------
1 TypeA Value1
2 TypeA Value2
3 TypeA Value3
4 TypeB Value20
5 TypeB Value21
6 TypeB Value22
7 TypeC Value1
8 TypeC Value2
因此,鉴于上述结构,我正在寻找一种方法来查询数据透视表,以便我可以计算TypeA
,TypeB
和{{中{{}}}中所有无效值的计数1}}其中TypeC
是有效日期,Date
不为空且大于0。
如何实现预期和输出的结果如下:
CountValue
我通过创建三个查询并使用UNION粘贴结果来完成结果,但我认为也应该可以使用数据透视表,但我不确定如何。可以使用数据透视表实现所需的结果吗?
注意:使用的数据库是SQL Server 2005数据库。
答案 0 :(得分:2)
我不会接近这个PIVOT,否则你必须转动你的数据,然后取消它以获得所需的输出。逐步分解,您可以使用以下方法获取有效的父ID:
SELECT t.ParentID
FROM #T AS t
GROUP BY t.ParentID
HAVING ISDATE(MAX(CASE WHEN t.Property = 'Date' THEN t.Value END)) = 1
AND MAX(CASE WHEN t.Property = 'CountValue' THEN CONVERT(INT, t.Value) END) > 0;
这两个条款将此限制为您拥有有效日期的条件,以及大于0的CountValue
下一步是找到无效的属性:
SELECT t.*
FROM #T AS t
WHERE NOT EXISTS
( SELECT 1
FROM #V AS v
WHERE v.Name = t.Property
AND v.Value = t.Value
);
这将包括Date和CountValue,并且也不包括TypeA
,因为所有属性都是有效的,因此需要更多的工作,我们必须找到我们感兴趣的不同属性:
SELECT DISTINCT Name
FROM #V
现在我们可以将它与无效属性结合起来获取计数,并使用有效的父ID来获得所需的结果:
WITH ValidParents AS
( SELECT t.ParentID
FROM #T AS t
GROUP BY t.ParentID
HAVING ISDATE(MAX(CASE WHEN t.Property = 'Date' THEN t.Value END)) = 1
AND MAX(CASE WHEN t.Property = 'CountValue' THEN CONVERT(INT, t.Value) END) > 0
), InvalidProperties AS
( SELECT t.Property
FROM #T AS t
WHERE t.ParentID IN (SELECT vp.ParentID FROM ValidParents AS vp)
AND NOT EXISTS
( SELECT 1
FROM #V AS v
WHERE v.Name = t.Property
AND v.Value = t.Value
)
)
SELECT [Count] = COUNT(t.Property),
[Column] = v.Name
FROM (SELECT DISTINCT Name FROM #V) AS V
LEFT JOIN InvalidProperties AS t
ON t.Property = v.Name
GROUP BY v.Name;
给出了:
Count Column
--------------
0 TypeA
1 TypeB
1 TypeC
查询以上查询
对于SQL Server 2008+。道歉,我没有SQL Server 2005了,忘了它不支持表值构造函数。
CREATE TABLE #T (Id INT, ParentId INT, Property VARCHAR(10), Value VARCHAR(10));
INSERT #T (Id, ParentId, Property, Value)
VALUES
(1, 1, 'Date', '01-09-2015'), (2, 1, 'CountValue', '2'), (3, 1, 'TypeA', 'Value1'),
(4, 1, 'TypeB', 'Value2'), (5, 1, 'TypeC', 'Value2'), (6, 2, 'Date', '15-10-2015'),
(7, 2, 'CountValue', '3'), (8, 2, 'TypeA', 'Value3'), (9, 2, 'TypeB', 'Value22'),
(10, 2, 'TypeC', 'Value99');
CREATE TABLE #V (ID INT, Name VARCHAR(5), Value VARCHAR(7));
INSERT #V (Id, Name, Value)
VALUES
(1, 'TypeA', 'Value1'), (2, 'TypeA', 'Value2'), (3, 'TypeA', 'Value3'),
(4, 'TypeB', 'Value20'), (5, 'TypeB', 'Value21'), (6, 'TypeB', 'Value22'),
(7, 'TypeC', 'Value1'), (8, 'TypeC', 'Value2');
答案 1 :(得分:1)
没有PIVOT
的最终结果:
SELECT [count] = SUM(CASE WHEN l.id IS NULL THEN 1 ELSE 0 END)
,t.Property
FROM #lookup l
RIGHT JOIN #tab t
ON t.Property = l.Name
AND t.Value = l.Value
WHERE t.Property LIKE 'Type%'
GROUP BY t.Property;
<强> LiveDemo 强>
数据:
CREATE TABLE #tab(
Id INTEGER NOT NULL PRIMARY KEY
,ParentId INTEGER NOT NULL
,Property VARCHAR(10) NOT NULL
,Value VARCHAR(10) NOT NULL
);
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (1,1,'Date','01-09-2015');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (2,1,'CountValue','2');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (3,1,'TypeA','Value1');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (4,1,'TypeB','Value2');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (5,1,'TypeC','Value2');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (6,2,'Date','15-10-2015');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (7,2,'CountValue','3');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (8,2,'TypeA','Value3');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (9,2,'TypeB','Value22');
INSERT INTO #tab(Id,ParentId,Property,Value) VALUES (10,2,'TypeC','Value99');
CREATE TABLE #lookup(
Id INTEGER NOT NULL PRIMARY KEY
,Name VARCHAR(5) NOT NULL
,Value VARCHAR(7) NOT NULL
);
INSERT INTO #lookup(Id,Name,Value) VALUES (1,'TypeA','Value1');
INSERT INTO #lookup(Id,Name,Value) VALUES (2,'TypeA','Value2');
INSERT INTO #lookup(Id,Name,Value) VALUES (3,'TypeA','Value3');
INSERT INTO #lookup(Id,Name,Value) VALUES (4,'TypeB','Value20');
INSERT INTO #lookup(Id,Name,Value) VALUES (5,'TypeB','Value21');
INSERT INTO #lookup(Id,Name,Value) VALUES (6,'TypeB','Value22');
INSERT INTO #lookup(Id,Name,Value) VALUES (7,'TypeC','Value1');
INSERT INTO #lookup(Id,Name,Value) VALUES (8,'TypeC','Value2');
修改强>
添加更多条件:
<强> LiveDemo2 强>
SELECT [count] = SUM(CASE WHEN l.id IS NULL THEN 1 ELSE 0 END)
,t.Property
FROM #lookup l
RIGHT JOIN #tab t
ON t.Property = l.Name
AND t.Value = l.Value
WHERE t.Property LIKE 'Type%'
AND t.ParentId IN (SELECT ParentId FROM #tab WHERE Property = 'Date' AND ISDATE(VALUE) = 1)
AND t.ParentID IN (SELECT ParentId FROM #tab WHERE Property = 'CountValue' AND Value > 0)
GROUP BY t.Property;