使用列数据过滤 SQL 行

Filtering SQL rows using column data

我正在尝试过滤单个 table 中的行。我的目标是 return 所有在 2021 年 7 月 28 日上午 11 点之前“进入”建筑物但尚未“离开”建筑物的车牌。

这是我编写的代码,当然 return 是当天的所有行。

SELECT *
FROM bakery_security_logs
WHERE day = '28' and
      month = '7' and
      year = '2021' and
      hour < '11'
ORDER BY month, day, year;

下面是这段代码 returns:

解决方案 1 - 分组并比较进入或退出的次数。

可以先按license_plate分组,统计车辆进出大楼的次数。如果大楼在上午11点之前进出,entranceCountexitCount应该是一样的。

但是,如果车辆于 11 月 27 日进入,并于 11 月 28 日离开,则此方法可能无效。

SELECT license_plate
FROM (
  SELECT
    license_plate,
    COUNT(CASE WHEN activity = 'entrance' THEN 1 ELSE NULL END) AS entranceCount,
    COUNT(CASE WHEN activity = 'exit' THEN 1 ELSE NULL END) AS exitCount
  FROM bakery_security_logs
  WHERE day = '28' and
        month = '7' and
        year = '2021' and
        hour < '11'
  GROUP BY license_plate
)
WHERE entranceCount > exitCount
-- WHERE entranceCount != exitCount
   -- if exitCount > entranceCount, may need to be alerted too

解决方案 2 - 获取最新记录并检查 activity

获取每个license_plate的最新记录。如果 activity = 'entrance',车辆在上午 11 点之前仍在大楼内。

这样效率更高,但语法可能会有所不同,具体取决于您使用的 SQL 服务器。


补充建议

使用DATETIME记录日期时间,这将有助于过滤和排序数据。

我喜欢这个 (MySQL) "one-liner":

SELECT 
        license_plate, 
        max(STR_TO_DATE(CONCAT(year, '-',  LPAD(month, 2, '0'), '-',  LPAD(day, 2, '0'), ' ', LPAD(hour, 2, '0'), ':', LPAD(minute, 2, '0')), '%Y-%m-%d %H:%i'))    date_time,
        max(activity) activity
    FROM bakery_security_logs
    WHERE day = '28' and
        month = '7' and
        year = '2021' and
        hour < '11'
    GROUP BY license_plate
    HAVING activity = 'entrance'
    ORDER BY date_time;