我做了一些我希望在一个表中组合的单个查询。每个查询检索F1,F2,F3的日期和值以及总数。
我想知道我是否可以使这个查询更容易,特别是如何实现这一点。所以更少的代码,但实现相同的事情。特别是当我想稍后将其扩展到F20时。
查询只需每15分钟将数据加在一起。
2017-09-20 10:15 |49.0000|f1.1
2017-09-20 10:15 |40.0000|f1.2
2017-09-20 10:15 |11.0000|f1.3
2017-09-20 10:15 |0.0000|f1.4
2017-09-20 10:15 |0.0000 |f1.5
2017-09-20 10:15 |0.0000 |f1.6
查询给了我日期的总和。 2017-09-20 10:15
如果我尝试条件聚合。它给出了所有deltavalues的总和。但它应该只对具有相同日期的值求和。
declare @days int
set @days = -165
SELECT a.Date, a.F1, b.F2, c.F3, d.Total
FROM
(SELECT rv.Date, sum(rv.value_num) as F1
FROM dbo.Channels c INNER JOIN
(SELECT rv.*, TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num, (LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16)) AS Date
FROM dbo.RecordedValues rv) rv ON c.SourceId = rv.SourceId AND c.Id = rv.ChannelId
WHERE c.Tag LIKE N'%F1%'
AND Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()
GROUP BY rv.Date
) as a,
(SELECT rv.Date, sum(rv.value_num) as F2
FROM dbo.Channels c INNER JOIN
(SELECT rv.*, TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num, (LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16)) AS Date
FROM dbo.RecordedValues rv) rv ON c.SourceId = rv.SourceId AND c.Id = rv.ChannelId
WHERE c.Tag LIKE N'%F2%'
AND Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()
GROUP BY rv.Date
) as b,
( SELECT rv.Date, sum(rv.value_num) as F3
FROM dbo.Channels c INNER JOIN
(SELECT rv.*, TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num, (LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16)) AS Date
FROM dbo.RecordedValues rv) rv ON c.SourceId = rv.SourceId AND c.Id = rv.ChannelId
WHERE c.Tag LIKE N'%F3%'
AND Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()
GROUP BY rv.Date
) as c,
(SELECT rv.Date, sum(rv.value_num) as Total
FROM dbo.Channels c INNER JOIN
(SELECT rv.*, TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num, (LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16)) AS Date
FROM dbo.RecordedValues rv) rv ON c.SourceId = rv.SourceId AND c.Id = rv.ChannelId
WHERE c.Tag LIKE N'%F%'
AND Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()
GROUP BY rv.Date
) as d
where a.Date = b.Date
AND b.Date = c.Date
AND c.Date = d.Date
这是它当前如何给出我的价值观:
RecDate F1 |F2 |F3 |Total
2017-09-20 10:15| 100 |200|100|400
2017-09-20 10:30| 150 |200|150|500
2017-09-20 10:45| 125 |200|100|425
2017-09-20 11:00| 110 |210|110|440
etc.
答案 0 :(得分:0)
您可以使用条件聚合来简化此代码:
SELECT rv.date,
SUM(CASE WHEN t.Tag LIKE N'%F1%' THEN rv.value_num ELSE 0 END) as f1,
SUM(CASE WHEN t.Tag LIKE N'%F2%' THEN rv.value_num ELSE 0 END) as f2,
SUM(CASE WHEN t.Tag LIKE N'%F3%' THEN rv.value_num ELSE 0 END) as f3,
SUM(CASE WHEN t.Tag LIKE N'%F%' THEN rv.value_num ELSE 0 END) as total
FROM dbo.channels t
JOIN (SELECT rv.*, TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num, (LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16)) AS Date
FROM dbo.RecordedValues rv
WHERE rv.Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()) rv
ON (c.SourceId = rv.SourceId AND c.Id = rv.ChannelId)
GROUP BY rv.Date
这样你只扫描一次表。
请注意,您应该使用每个列的别名 - > Timestamp
没有别名,我不知道它来自哪个表。
答案 1 :(得分:0)
我认为你只需要条件聚合
SELECT rv.Date,
SUM(CASE WHEN c.Tag LIKE N'%F%' THEN rv.value_num END) as Total,
SUM(CASE WHEN c.Tag LIKE N'%F1%' THEN rv.value_num END) as F1,
SUM(CASE WHEN c.Tag LIKE N'%F2%' THEN rv.value_num END) as F2,
SUM(CASE WHEN c.Tag LIKE N'%F3%' THEN rv.value_num END) as F3
FROM dbo.Channels c
INNER JOIN (
SELECT rv.*,
TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num,
LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16) AS Date
FROM dbo.RecordedValues rv
) rv ON c.SourceId = rv.SourceId AND c.Id = rv.ChannelId
AND Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()
GROUP BY rv.Date
答案 2 :(得分:0)
在您当前的查询中,您正在交叉连接所有性能最差的表。而是使用Case..When
,因为它似乎是解决问题的最佳方法。
由于我不知道时间戳和日期转换背后的架构和原因,我所能建议的是跟随查询:
declare @days int
set @days = -165
SELECT rv.Date,
sum(case when c.Tag LIKE N'%F1%' then rv.value_num else 0 end) as F1,
sum(case when c.Tag LIKE N'%F2%' then rv.value_num else 0 end) as F2,
sum(case when c.Tag LIKE N'%F3%' then rv.value_num else 0 end) as F3,
sum(case when c.Tag LIKE N'%F%' then rv.value_num else 0 end) as total,
FROM dbo.Channels c
INNER JOIN
(SELECT rv.*, TRY_CONVERT(numeric(20, 4), rv.Value) AS value_num,
(LEFT(TRY_CONVERT(datetime2(0), rv.Timestamp), 16)) AS Date
FROM dbo.RecordedValues rv) rv
ON c.SourceId = rv.SourceId AND c.Id = rv.ChannelId
WHERE
rv.Timestamp BETWEEN DATEADD(day,@days,GETDATE()) AND GETDATE()
GROUP BY rv.Date;
希望它有所帮助!