使用PIVOT
SELECT id, _TIMESTAMP, [Tag1], [Tag2], [Tag3], [Tag4], [Tag5], [Tag6]
FROM (SELECT id, _VALUE, _NAME, _TIMESTAMP
FROM [dbo].[TableLogger]) AS SourceTable PIVOT (MAX(_VALUE) FOR _NAME IN ([Tag1], [Tag2], [Tag3], [Tag4], [Tag5], [Tag6])) AS PivotTable
我的表看起来像这样:
id _TIMESTAMP Tag1 Tag2 Tag3 Tag4 Tag5 Tag6 1 2016-04-29 10:37:56.667 21 NULL NULL NULL NULL NULL 2 2016-04-29 10:37:56.667 NULL 0.2 NULL NULL NULL NULL 3 2016-04-29 10:37:56.667 NULL NULL 4 NULL NULL NULL 4 2016-04-29 10:37:56.667 NULL NULL NULL 20 NULL NULL 5 2016-04-29 10:37:56.667 NULL NULL NULL NULL 35 NULL 6 2016-04-29 10:37:56.667 NULL NULL NULL NULL NULL 54 7 2016-04-29 10:37:58.667 32 NULL NULL NULL NULL NULL
该表有30471行,可以获得更多。 SELECT
语句的执行过多(如10s)。我尝试使用以下命令删除这些NULL值:
where [Tag1] IS NOT NULL ;
如果我想同时放置相同的条件,并且对于[Tag2]列,表格不再显示。我猜那些NULL值会影响SELECT执行的时间。有没有办法删除那些NULL值,以便我的SELECT语句执行得更快? 提前谢谢了!
修改
我希望看到我的表格:
id _TIMESTAMP Tag1 Tag2 Tag3 Tag4 Tag5 Tag6 1 2016-04-29 10:37:56.667 21 0.2 4 20 35 54 2 2016-04-29 10:37:58.667 32 25 65 32 30 13
答案 0 :(得分:0)
有时使用Case Expressions而不是Pivot可以获得更好的性能。要做一个真正的Pivot虽然你不能拥有不属于聚合的唯一字段(ID)或你得到那些空值
SELECT _TIMESTAMP,
MAX(CASE WHEN _NAME = 'Tag1' THEN _VALUE END) AS Tag1,
MAX(CASE WHEN _NAME = 'Tag2' THEN _VALUE END) AS Tag2,
MAX(CASE WHEN _NAME = 'Tag3' THEN _VALUE END) AS Tag3,
etc..
FROM TableLogger
GROUP BY _TIMESTAMP
测试用例
DECLARE @TableLogger TABLE (id int, _TIMESTAMP datetime, _NAME varchar(MAX), _VALUE FLOAT)
INSERT INTO @TableLogger VALUES
(1, '2016-04-29 10:37:56.667', 'Tag1', 21),
(2, '2016-04-29 10:37:56.667', 'Tag2', 0.2),
(3, '2016-04-29 10:37:56.667', 'Tag3', 4),
(4, '2016-04-29 10:37:56.667', 'Tag4', 20),
(5, '2016-04-29 10:37:56.667', 'Tag5', 35),
(6, '2016-04-29 10:37:56.667', 'Tag6', 54),
(7, '2016-04-29 10:37:58.667', 'Tag1', 32),
(8, '2016-04-29 10:37:58.667', 'Tag2', 25),
(9, '2016-04-29 10:37:58.667', 'Tag3', 65),
(10, '2016-04-29 10:37:58.667', 'Tag4', 32),
(11, '2016-04-29 10:37:58.667', 'Tag5', 30),
(12, '2016-04-29 10:37:58.667', 'Tag6', 13)
-- CORRECT WAY TO PIVOT
SELECT _TIMESTAMP,
MAX(CASE WHEN _NAME = 'Tag1' THEN _VALUE END) AS Tag1,
MAX(CASE WHEN _NAME = 'Tag2' THEN _VALUE END) AS Tag2,
MAX(CASE WHEN _NAME = 'Tag3' THEN _VALUE END) AS Tag3,
MAX(CASE WHEN _NAME = 'Tag4' THEN _VALUE END) AS Tag4,
MAX(CASE WHEN _NAME = 'Tag5' THEN _VALUE END) AS Tag5,
MAX(CASE WHEN _NAME = 'Tag6' THEN _VALUE END) AS Tag6
FROM @TableLogger
GROUP BY _TIMESTAMP
-- INCORRECT WAY TO PIVOT
-- Including ID will cause each row to only have one value
SELECT ID
_TIMESTAMP,
MAX(CASE WHEN _NAME = 'Tag1' THEN _VALUE END) AS Tag1,
MAX(CASE WHEN _NAME = 'Tag2' THEN _VALUE END) AS Tag2,
MAX(CASE WHEN _NAME = 'Tag3' THEN _VALUE END) AS Tag3,
MAX(CASE WHEN _NAME = 'Tag4' THEN _VALUE END) AS Tag4,
MAX(CASE WHEN _NAME = 'Tag5' THEN _VALUE END) AS Tag5,
MAX(CASE WHEN _NAME = 'Tag6' THEN _VALUE END) AS Tag6
FROM @TableLogger
GROUP BY ID, _TIMESTAMP
-- WAYS TO INCLUDE ROW NUMBER OR ID IN PIVOT
SELECT ROW_NUMBER() OVER (ORDER BY _TIMESTAMP) AS [RowNumber],
MIN(ID) [MinID],
_TIMESTAMP,
MAX(CASE WHEN _NAME = 'Tag1' THEN _VALUE END) AS Tag1,
MAX(CASE WHEN _NAME = 'Tag2' THEN _VALUE END) AS Tag2,
MAX(CASE WHEN _NAME = 'Tag3' THEN _VALUE END) AS Tag3,
MAX(CASE WHEN _NAME = 'Tag4' THEN _VALUE END) AS Tag4,
MAX(CASE WHEN _NAME = 'Tag5' THEN _VALUE END) AS Tag5,
MAX(CASE WHEN _NAME = 'Tag6' THEN _VALUE END) AS Tag6
FROM @TableLogger
GROUP BY _TIMESTAMP
-- A CORRECT PIVOT QUERY
SELECT * FROM
(
SELECT _TIMESTAMP, _NAME, _VALUE
FROM @TableLogger tl
) t
PIVOT
(
MAX(_VALUE)
FOR _NAME IN ([Tag1],[Tag2],[Tag3],[Tag4],[Tag5],[Tag6])
) pt
-- AN INCORRECT PIVOT QUERY
SELECT * FROM
(
SELECT ID, -- OOPS, included ID
_TIMESTAMP, _NAME, _VALUE
FROM @TableLogger tl
) t
PIVOT
(
MAX(_VALUE)
FOR _NAME IN ([Tag1],[Tag2],[Tag3],[Tag4],[Tag5],[Tag6])
) pt
-- GIMME THOSE DARN ID's IN MA PIVOT
SELECT ROW_NUMBER() OVER (ORDER BY _TIMESTAMP) AS [RowNumber],
*
FROM
(
SELECT MIN(ID) OVER (PARTITION BY _TIMESTAMP) [MinID],
_TIMESTAMP, _NAME, _VALUE
FROM @TableLogger tl
) t
PIVOT
(
MAX(_VALUE)
FOR _NAME IN ([Tag1],[Tag2],[Tag3],[Tag4],[Tag5],[Tag6])
) pt