假设我有日期时间格式的日期列表:
6/30/2015 10:44:44 PM
6/30/2015 11:00:24 PM
7/1/2015 12:22:46 AM
7/1/2015 12:26:38 AM
7/1/2015 2:55:04 AM
7/1/2015 3:23:00 AM
7/1/2015 3:32:09 AM
7/1/2015 3:52:27 AM
7/1/2015 3:57:25 AM
7/1/2015 4:03:34 AM
7/1/2015 4:23:52 AM
7/1/2015 4:32:00 AM
7/1/2015 4:50:03 AM
7/1/2015 4:54:46 AM
7/1/2015 5:10:20 AM
7/1/2015 5:13:37 AM
7/1/2015 5:18:51 AM
....
7/31/2015 11:18:51 PM
我想抓住列表中每个日期的最近时间到5 AM。 我应该怎么做呢?
SELECT TOP 1 *
FROM x
WHERE x.date < @CurrentDate
ORDER BY x.date DESC
应该抓住最近的日期到当前日期,但每个不同的日期?
答案 0 :(得分:3)
您可以使用TIMEDIFF
和TIME_TO_SEC
方法获取其他日期的“最近”日期:
SELECT
d
FROM
test
ORDER BY
ABS(TIME_TO_SEC(TIMEDIFF(d, "2015-10-23 19:00:00")))
LIMIT
0,1 ;
http://sqlfiddle.com/#!9/5b67f/2
要获取每日的关闭日期和可用条目,您需要扩展此查询,因此它不会与固定日期进行比较,而是“每天上午5点”:
实现这一目标:
DATE(d)
date
(或min(date)
)因分组而可能出错的问题*(请注意帖子末尾)我们定位的日期加上(或减去)偏移量(由于分组以及min()
聚合而正确)在示例DATE_ADD(DATE(d), INTERVAL 19 HOUR)
中用于确定当前行的7 pm
。对于5 am
,它将是DATE_ADD(DATE(d), INTERVAL 5 HOUR)
:
(我在查询中留下了调试列,可以删除它们。你只需要actualDate
- 列)
SELECT
DATE(d) AS day,
MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR))))) AS offset,
MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) AS controlOffset1,
MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) AS controlOffset2,
CASE
WHEN MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR))))) = MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) && MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) > 0 THEN
DATE_Add(DATE_ADD(DATE(d), INTERVAL 19 HOUR), INTERVAL
MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))))
SECOND)
WHEN MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR))))) = MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) THEN
DATE_SUB(DATE_ADD(DATE(d), INTERVAL 19 HOUR), INTERVAL
MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))))
SECOND)
WHEN MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) = MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) THEN
DATE_ADD(DATE_ADD(DATE(d), INTERVAL 19 HOUR), INTERVAL
MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))))
SECOND)
WHEN MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) <> MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) THEN
DATE_SUB(DATE_ADD(DATE(d), INTERVAL 19 HOUR), INTERVAL
MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))))
SECOND)
END AS actualDate,
case
WHEN MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR))))) = MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) && MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) > 0 THEN
"TEST#1"
WHEN MIN(ABS(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR))))) = MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) THEN
"TEST#2"
WHEN MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) = MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) THEN
"TEST#3"
WHEN MIN(TIME_TO_SEC(TIMEDIFF(d, DATE_ADD(DATE(d), INTERVAL 19 HOUR)))) <> MIN(TIME_TO_SEC(TIMEDIFF(DATE_ADD(DATE(d), INTERVAL 19 HOUR),d))) THEN
"TEST#4"
END AS testCase
FROM
test
GROUP BY DATE(d)
数据:
CREATE table test (d datetime);
# TEST 1: Solution later
INSERT INTO test (d) values ("2015-10-23 19:10:00"); #this
INSERT INTO test (d) values ("2015-10-23 19:20:00");
INSERT INTO test (d) values ("2015-10-23 19:30:00");
INSERT INTO test (d) values ("2015-10-23 19:40:00");
INSERT INTO test (d) values ("2015-10-23 19:50:00");
# TEST 2: Solution earlier
INSERT INTO test (d) values ("2015-10-24 18:10:00");
INSERT INTO test (d) values ("2015-10-24 18:20:00");
INSERT INTO test (d) values ("2015-10-24 18:30:00");
INSERT INTO test (d) values ("2015-10-24 18:40:00");
INSERT INTO test (d) values ("2015-10-24 18:50:00");#this
# TEST 3: Solution later, but earlier available
INSERT INTO test (d) values ("2015-10-25 18:30:00");
INSERT INTO test (d) values ("2015-10-25 18:40:00");
INSERT INTO test (d) values ("2015-10-25 18:50:00");
INSERT INTO test (d) values ("2015-10-25 19:05:00"); #this
INSERT INTO test (d) values ("2015-10-25 19:10:00");
INSERT INTO test (d) values ("2015-10-25 19:20:00");
INSERT INTO test (d) values ("2015-10-25 19:30:00");
# Test 4: Solution earlier, but later available
INSERT INTO test (d) values ("2015-10-26 18:30:00");
INSERT INTO test (d) values ("2015-10-26 18:40:00");
INSERT INTO test (d) values ("2015-10-26 18:50:00");
INSERT INTO test (d) values ("2015-10-26 18:55:00"); #this
INSERT INTO test (d) values ("2015-10-26 19:10:00");
INSERT INTO test (d) values ("2015-10-26 19:20:00");
INSERT INTO test (d) values ("2015-10-26 19:30:00");
INSERT INTO test (d) values ("2015-10-26 19:40:00");
结果:
day offset controlOffset1 controlOffset2 actualDate testCase
October, 23 2015 00:00:00 600 600 -3000 October, 23 2015 19:10:00 TEST#1
October, 24 2015 00:00:00 600 -3000 600 October, 24 2015 18:50:00 TEST#2
October, 25 2015 00:00:00 300 -1800 -1800 October, 25 2015 19:05:00 TEST#3
October, 26 2015 00:00:00 300 -1800 -2400 October, 26 2015 18:55:00 TEST#4
http://sqlfiddle.com/#!9/951b5/22
说明:
Min(Abs())
偏移时,我们需要弄清楚,如果我们需要add
此偏移量为7pm
值,或subtract
它。< / LI>
MIN(actualDate - 7pm)
MIN(7pm - actualDate)
DATE_ADD
DATE_SUB
DATE_ADD
DATE_SUB
: - )如果两个日期是+/-且具有相同的偏移量,即+/- 5分钟,那么暗示的唯一内容现在可能是。因此,无论如何结果都是未确定的,因此您应该通过使用>=
或<=
扩展某些条件来获取非空值。 (编辑:将与案例3匹配,选择较晚的日期:http://sqlfiddle.com/#!9/21f2ce/2)
ps:与应用程序端迭代方法中的“单次提取”相比,最终解决方案在性能方面的表现会很有趣。
*比较偏移量:为什么Min(d - 7pm)
的偏移量不同于Min(7pm -d)
- 而且不仅仅是符号?因为缺少聚合而导致d
未确定。因此,使用两个控制偏移量,我们可以根据7pm
确定值, 正确聚合,因此可靠。)
答案 1 :(得分:0)
在平等时间凌晨5点之前和之后考虑:
select d, min(if(diff < 0, subtime(subtime(diff,diff),diff), diff)) diff from(
select date(d) d, timediff(time(d), maketime(5,0,0)) diff from dt
) q
group by d;