我们正在使用SQL Server 2016:
这是我当前的表格:
countx RunDateTime
104 7/15/20 0:05
104 7/15/20 0:10
102 7/15/20 0:15
102 7/15/20 0:20
100 7/15/20 0:25
100 7/15/20 0:30
102 7/15/20 0:35
99 7/15/20 0:40
97 7/15/20 0:46
99 7/15/20 0:56
93 7/15/20 1:01
93 7/15/20 1:10
93 7/15/20 1:16
91 7/15/20 1:31
89 7/15/20 1:39
87 7/15/20 1:57
88 7/15/20 2:05
80 7/15/20 2:11
81 7/15/20 2:20
我只想要以下结果
countx RunDateTime 104 7/15/20 0:05 100 7/15/20 0:30 93 7/15/20 1:01 91 7/15/20 1:31 88 7/15/20 2:05
如何仅选择最接近最近的30分钟间隔的行?
我只希望最接近小时且最接近半小时的行
例如,我只希望最靠近的行
00:00和00:30
01:00和01:30
02:00和02:30
等
我能够选择最接近小时的行,但是我不知道如何获取最接近半小时的数据。这是我尝试过的。
SELECT
RunDateTime,
COUNT(DISTINCT id) countxbyhour
FROM (SELECT
t.*,
MIN(RunDateTime) OVER(PARTITION BY CAST(RunDateTime AS DATE),
DATEPART(HOUR,RunDateTime)) mintmstmp
FROM table t) x
WHERE RunDateTime = mintmstmp
GROUP BY RunDateTime
ORDER BY RunDateTime
答案 0 :(得分:0)
尝试一下...
IF OBJECT_ID('tempdb..#Table') IS NOT NULL DROP TABLE #Table
SELECT * INTO #Table FROM (VALUES
(104, CAST('7/15/20 0:05' as datetime)),
(104, '7/15/20 0:10'),
(102, '7/15/20 0:15'),
(102, '7/15/20 0:20'),
(100, '7/15/20 0:25'),
(100, '7/15/20 0:30'),
(102, '7/15/20 0:35'),
(99, '7/15/20 0:40'),
(97, '7/15/20 0:46'),
(99, '7/15/20 0:56'),
(93, '7/15/20 1:01'),
(93, '7/15/20 1:10'),
(93, '7/15/20 1:16'),
(91, '7/15/20 1:31'),
(89, '7/15/20 1:39'),
(87, '7/15/20 1:57'),
(88, '7/15/20 2:05'),
(80, '7/15/20 2:11'),
(81, '7/15/20 2:20')
) S(countx, RunDateTime);
SELECT * FROM #Table;
WITH DataSource AS (
SELECT
*,
CASE WHEN DATEPART(MINUTE, RunDateTime) >= 30
THEN (DATEPART(MINUTE, RunDateTime) - 30) / 30.0
ELSE DATEPART(MINUTE, RunDateTime) / 30.0
END FracHalfour
FROM
#Table
)
SELECT
D.countx, D.RunDateTime
FROM
DataSource D
JOIN (
SELECT
countx,
MIN(FracHalfour) FracHalfour
FROM
DataSource S
GROUP BY
countx
) S ON
S.countx = D.countx AND
S.FracHalfour = D.FracHalfour
ORDER BY
countx DESC
答案 1 :(得分:0)
Jason击败了我,这是我的版本:
SELECT
t.countx,
t.RunDateTime
FROM
test t
WHERE
DATEPART(minute,t.RunDateTime) BETWEEN 0 AND 5
OR (DATEPART(minute,t.RunDateTime) > 25 AND DATEPART(minute,t.RunDateTime) < 35)
OR DATEPART(minute,t.RunDateTime) > 55
答案 2 :(得分:0)
如果最接近的意思是指半小时后的第一个时间值:
with data as (
select *, row_number() over (
partition by dateadd(minute, -datepart(minute, RunDateTime) % 30, RunDateTime)
order by RunDateTime
) as rn
from t
)
select * from data where rn = 1;
这基本上是通过简单的演绎来截断多余的分钟。我假设不涉及(毫秒)秒。
您还可以通过在“截断”操作之前加上15分钟并取距离的绝对值,将其“舍入”到最近的半小时:
with data as (
select *, row_number() over (
partition by dateadd(minute, -datepart(minute, shiftedDt) % 30, shiftedDt)
order by abs(datediff(minute, RunDateTime, dateadd(minute, -datepart(minute, RunDateTime) % 30, RunDateTime))), RunDateTime
) as rn
from t cross apply ( values (dateadd(minute, 15, RunDateTime)) ) as s(shiftedDt)
)
select * from data where rn = 1;
关系在哪里发挥作用,需要较早的关系。另外,如果要在样本数据上使用此方法,它将返回一组不同的行。
答案 3 :(得分:0)
基于Jason的:
declare @t table(countx int, RunDateTime datetime);
insert into @t values
(104, '7/15/20 0:05'),
(104, '7/15/20 0:10'),
(102, '7/15/20 0:15'),
(102, '7/15/20 0:20'),
(100, '7/15/20 0:25'),
(100, '7/15/20 0:30'),
(102, '7/15/20 0:35'),
(99, '7/15/20 0:40'),
(97, '7/15/20 0:46'),
(99, '7/15/20 0:56'),
(93, '7/15/20 1:01'),
(93, '7/15/20 1:10'),
(93, '7/15/20 1:16'),
(91, '7/15/20 1:31'),
(89, '7/15/20 1:39'),
(87, '7/15/20 1:57'),
(88, '7/15/20 2:05'),
(80, '7/15/20 2:11'),
(81, '7/15/20 2:20');
WITH CTE AS
(--get data and dif
select *, ROW_NUMBER() OVER (PARTITION BY (countx) ORDER BY (CASE WHEN DATEPART(MINUTE, RunDateTime) >= 30
THEN (DATEPART(MINUTE, RunDateTime) - 30) / 30.0
ELSE DATEPART(MINUTE, RunDateTime) / 30.0
END)) as rowno
from @t
)
select *
from
CTE
where
CTE.rowno = 1;
答案 4 :(得分:0)
我使用了Jasons代码中的一些想法来划分日期部分:
select
RunDateTime,
count(distinct id) Countx
from (
select t.*,
min(RunDateTime) over(
partition by cast(RunDateTime as date),( datepart(hour,RunDateTime)*100+CASE WHEN DATEPART(MINUTE, RunDateTime) >= 30
THEN 30
ELSE 00 end )) mintmstmp
from table t
) x
where RunDateTime=mintmstmp
group by RunDateTime
order by RunDateTime