我有一个包含时间戳和方向(输入/输出)的表
CASE 1:in, 2016-07-06 08:00:00, I
CASE 1:out, 2016-07-06 17:00:00, O
CASE 2:in, 2016-07-12 08:00:00, I
CASE 2:out, 2016-07-13 17:00:00, O
CASE 3:in, 2016-07-14 08:00:00, I
CASE 3:out, 2016-07-18 17:00:00, O
我想创建一个选项,向我显示每天早上03点都进入的所有行。它还应该向我展示它所处的几个月的所有日子。
正如您从示例中看到的那样,不应该返回案例1,因为它在凌晨03:00不是。
到目前为止,我已经创建了一个select语句来检查特定日期:
Select t.* from
(SELECT * FROM movement
where scan_date < '2016-07-06 03:00:00'
order by scan_date desc limit 1) t
WHERE t.direction='I';
到目前为止一切顺利。我现在想检查整个月。 为简单起见,我创建了一个包含整个月的所有3am entiries的表格:
Select day from month
返回
2017-07-01 03:00:00 ......等等......
由于某种原因,我无法将这两个选择结合起来。 我不能使用&lt;中的第二个表。因为它告诉我它返回的行多了一行。
问题听起来很简单但到目前为止还没有找到解决方案。 如果有人有任何想法我会很高兴听到它。
答案 0 :(得分:1)
鉴于您更新的问题陈述,以下内容应该让您入门:
SELECT
check_time
, CAST(LEFT(checktime_direction, 19) AS DATETIME) scan_time
, RIGHT(checktime_direction, 1) direction
FROM (
SELECT
CP.p check_time
, (SELECT CONCAT(DATE_FORMAT(scan_date, '%Y-%m-%d %H:%i:%s'), direction)
FROM Movement
WHERE scan_date = (SELECT MAX(scan_date)
FROM Movement
WHERE scan_date <= CP.p
)
) checktime_direction
FROM Checkpoint CP
) T
WHERE RIGHT(checktime_direction, 1) = 'I'
ORDER BY check_time
;
对于您的样本数据,它返回:
| check_time | scan_time | direction |
|------------------------|------------------------|-----------|
| July, 13 2016 03:00:00 | July, 12 2016 08:00:00 | I |
| July, 15 2016 03:00:00 | July, 14 2016 08:00:00 | I |
| July, 16 2016 03:00:00 | July, 14 2016 08:00:00 | I |
| July, 17 2016 03:00:00 | July, 14 2016 08:00:00 | I |
| July, 18 2016 03:00:00 | July, 14 2016 08:00:00 | I |
查看实际操作:SQL Fiddle 注意:帮助者表格被称为检查点而不是月,因为后者是MySQL reserved word。
整体解决方案方法是使用correlated (or "synchronized") subquery 一般而言,内部查询为相应的外部检查点提取最近的方向变化。反过来(中间)结果集被过滤以仅保留“I”记录。
详细说明:
SELECT
CP.p check_time
[...]
FROM Checkpoint CP
是外部查询,设置场景。 (在所提到的同步的上下文中,也就是说。为了得到想要的结果,这个“外部”查询本身就被包装了。 - 但这不涉及相关,只是过滤。)
SELECT MAX(scan_date)
FROM Movement
WHERE scan_date <= CP.p
通过 CP.p 链接到它 当您要求提取 scan_date 和方向以获得最终结果时,会在两者之间引入另一个级别:
SELECT CONCAT(DATE_FORMAT(scan_date, '%Y-%m-%d %H:%i:%s'), direction)
FROM Movement
WHERE scan_date = ([...]
)
此查询有两列 - 但其输出需要适合外部查询中的单个列。因此,两列组合成一列 - 以确保以后正确拆卸。
从这里开始,剩下要做的就是摆脱“O”记录(并将剩余的记录放入正确的顺序)。好吧 - 早先合并为一列 scan_time 和方向等待分离(前者返回DATETIME
):
SELECT
check_time
, CAST(LEFT(checktime_direction, 19) AS DATETIME) scan_time
, RIGHT(checktime_direction, 1) direction
FROM (
[...]
) T
WHERE RIGHT(checktime_direction, 1) = 'I'
ORDER BY check_time
;
你可能想要使用小提琴,分开查询,玩碎片,观看节目......
注意每个子选择周围的一对圆括号/圆括号。这些是SQL语法所必需的。
请评论是否需要调整/进一步详细说明。
答案 1 :(得分:0)
Select movement.*
from month
inner join movement ON scan_date < month.day AND direction='I'
GROUP BY month.day
ORDER BY movement.scan_date DESC
我希望这对你有用。
答案 2 :(得分:0)
select *, extract(day from scan_date) as days_of_month
from movement where extract(hour from scan_date) = 3
and direction='I'
order by scan_date desc;
如果您还需要更多信息,请使用表格结构进行解释。