不能将两个选择结合在一起

时间:2016-07-13 06:42:58

标签: mysql sql

我有一个包含时间戳和方向(输入/输出)的表

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;中的第二个表。因为它告诉我它返回的行多了一行。

问题听起来很简单但到目前为止还没有找到解决方案。 如果有人有任何想法我会很高兴听到它。

3 个答案:

答案 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;

如果您还需要更多信息,请使用表格结构进行解释。