表:我在SQL Server 2012中有一个数据库表mytable1。表定义是
Column_name Type Length Nullable
ts datetime 8 no
s_no int 4 no
calls int 4 yes
DDL :并使用
创建CREATE TABLE mytable1(
ts DATETIME NOT NULL,
s_no INT NOT NULL,
calls INT
);
填充数据
INSERT INTO mytable1 (ts, s_no, calls)
VALUES
('2016-10-14 10:04:01.000', 3, 56),
('2016-10-14 10:04:01.000', 4, 145),
('2016-10-14 10:09:00.000', 3, 143),
('2016-10-14 10:09:00.000', 4, 329),
('2016-10-14 10:14:01.000', 3, 0),
('2016-10-14 10:14:01.000', 4, 49),
('2016-10-14 10:19:00.000', 3, 6),
('2016-10-14 10:19:00.000', 4, 16),
('2016-10-14 10:24:01.000', 3, 22),
('2016-10-14 10:24:01.000', 4, 28),
('2016-10-14 10:29:00.000', 3, 4),
('2016-10-14 10:29:00.000', 4, 7),
('2016-10-14 10:34:00.000', 3, 14),
('2016-10-14 10:34:00.000', 4, 9),
('2016-10-14 10:38:59.000', 3, 39),
('2016-10-14 10:38:59.000', 4, 391),
('2016-10-14 10:44:01.000', 3, 3),
('2016-10-14 10:44:01.000', 4, 31),
('2016-10-14 10:49:01.000', 3, 116),
('2016-10-14 10:49:01.000', 4, 52),
('2016-10-14 10:54:00.000', 3, 75),
('2016-10-14 10:54:00.000', 4, 8),
('2016-10-14 10:59:00.000', 3, 16),
('2016-10-14 10:59:00.000', 4, 8),
('2016-10-14 11:04:01.000', 3, 23),
('2016-10-14 11:04:01.000', 4, 13);
我正在尝试将时间戳划分为30分钟的窗口,然后从每个30分钟的窗口中选择最大的时间戳。此外,我想为最高的30分钟时间戳选择所有不同的s_no值。
现有查询:我有一个执行此操作的查询
select m.s_no, m.bucket_window, max(m.ts) ts
from (
select m.*, datepart(hour, m.ts)*2 + floor(datepart(minute, m.ts)/30) bucket_window
from mytable1 m
where m.ts >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
) m
group by m.s_no, m.bucket_window;
结果:结果为
s_no bucket_window ts
3 20 2016-10-14 10:29:00.000
4 20 2016-10-14 10:29:00.000
3 21 2016-10-14 10:59:00.000
4 21 2016-10-14 10:59:00.000
3 22 2016-10-14 11:04:01.000
4 22 2016-10-14 11:04:01.000
现在我想改进此查询并在上面的结果中添加列调用。此列应具有 mytable1 表的调用列的值,其中 s_no 和 ts 的组合来自上述结果匹配来自 mytable1 表的 s_no 和 ts 的组合。
预期结果:我现在想要的结果是
s_no bucket_window ts calls
3 20 2016-10-14 10:29:00.000 4
4 20 2016-10-14 10:29:00.000 7
3 21 2016-10-14 10:59:00.000 16
4 21 2016-10-14 10:59:00.000 8
3 22 2016-10-14 11:04:01.000 23
4 22 2016-10-14 11:04:01.000 13
我尝试使用连接,但无法将查询与正确的语法结合在一起:
我尝试了什么:
select m.s_no, m.bucket_window, max(m.ts) ts, i.calls
from (
select m.*, datepart(hour, m.ts)*2 + floor(datepart(minute, m.ts)/30) bucket_window
from mytable1 m
where m.ts >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
) m
LEFT JOIN mytable1 i
ON max(m.ts) = i.ts--OR (m.ts) = i.ts
group by m.s_no, m.bucket_window, i.calls
请建议我如何修改此现有查询以获得预期结果。
由于此现有查询在生产中使用了很长时间,并在其他动态生成的查询中用作子查询,因此我不想完全更改它以获得预期结果。
答案 0 :(得分:1)
试试这个
SELECT M1.*,
(SELECT calls From mytable1 M2 where M2.ts=M1.ts and M2.s_no=M1.s_no) as calls
FROM
(
select m.s_no, m.bucket_window, max(m.ts) ts
from (
select m.*, datepart(hour, m.ts)*2 + floor(datepart(minute, m.ts)/30) bucket_window
from mytable1 m
where m.ts >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
) m
group by m.s_no, m.bucket_window
) M1
答案 1 :(得分:1)
好的,让我看看这是否可以帮到你:
select s_no, bucket_window, ts, c as calls from (
select s_no, ts, bucket_window,
max(ts) over (partition by s_no, bucket_window) maxts,
case
when ts=max(ts) over (partition by s_no, bucket_window)
then calls
end c
from (
select m.*,
datepart(hour, m.ts)*2 + floor(datepart(minute, m.ts)/30) bucket_window
from mytable1 m
where m.ts >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
) x
) y
where ts=maxts;
我从您的初始查询开始,但尝试不必再次加入mytable1。我不知道SQL Server语法,但我在rextester上测试了它,它说它应该工作。
这是我在rextester上准备的例子:我把所有三个可用解决方案放在一起,他们似乎都给出了你要求的答案。
由于我不了解SQL Server语法,因此我使用了我可能在Teradata或Oracle上使用的SQL标准分析函数来修改您的查询。
答案 2 :(得分:0)
使用top(1)with ties .. order by row_number()
select top(1) with ties m.s_no, datepart(hour, m.ts)*2 + floor(datepart(minute, m.ts)/30) bucket_window, ts, calls
from mytable1 m
where m.ts >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
order by row_number() over (partition by m.s_no, datepart(hour, m.ts)*2 + floor(datepart(minute, m.ts)/30)
order by ts desc);