【问题标题】:PHP/MySQL Select the day before and day after a range from the same tablePHP/MySQL 从同一个表中选择一个范围的前一天和后一天
【发布时间】:2013-12-09 23:32:46
【问题描述】:

我有两张桌子,一张叫 check_ins,另一张叫 holiday。

check_ins 有一个 datetime_start 和 datetime_end 列(除了这个问题不需要的其他东西)。假期表的日期范围为假期开始和结束的两列。

我需要弄清楚谁在假期的前一天和第二天的假期范围内,以确定谁获得假期工资。换句话说,我只需要同一员工在前一天和后一天的表中的结果,而忽略其余的。

我整天绞尽脑汁想办法做到这一点,但一无所获。我在这里叫错树了吗?我应该通过 PHP 执行此操作吗?

谢谢!

编辑:这是我使用的,虽然我有它,直到我意识到他们可能在一天内多次签到:

SELECT DISTINCT count(check_ins.Employee_ID), check_ins.ShiftStart_Datetime, check_ins.ShiftEnd_Datetime, holidays.* FROM check_ins, holidays WHERE holidays.ID = 2 AND DATE(DATE_ADD(Datefrom, INTERVAL -1 DAY)) = DATE(ShiftStart_Datetime) GROUP BY Employee_ID HAVING count(check_ins.Employee_ID) >1 UNION SELECT DISTINCT check_ins.Employee_ID, check_ins.ShiftStart_Datetime, check_ins.ShiftEnd_Datetime, holidays.* FROM check_ins, holidays WHERE DATE(DATE_SUB(Dateto, INTERVAL -1 DAY)) = DATE(ShiftStart_Datetime) GROUP BY Employee_ID HAVING count(check_ins.Employee_ID) >1

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    您可以(内部)加入check_ins 表两次。假期开始前一天一次,后一天一次。

    如果datetime_startdatetime_end 可能有不同的日期,则需要使用BETWEEN。将它们都转换为日期而不是日期时间,因为您不关心时间。

    添加GROUP BY,以防员工一天有多次签到。

    SELECT holidays.id AS holiday_id, ci_before.employee_id FROM holidays 
       INNER JOIN check_ins ci_before ON holidays.holiday_start - INTERVAL 1 DAY
           BETWEEN DATE(ci_before.datetime_start) AND DATE(ci_before.datetime_end)
       INNER JOIN check_ins ci_after ON holidays.holiday_end + INTERVAL 1 DAY
           BETWEEN DATE(ci_after.datetime_start) AND DATE(ci_after.datetime_end)
           AND ci_before.employee_id = ci_after.employee_id
    GROUP BY ci_before.employee_id
    

    See the SQL fiddle here

    使用的表是

    CREATE TABLE `holidays` (id int, holiday_start date, holiday_end date);
    CREATE TABLE `check_ins` (employee_id int, datetime_start datetime, datetime_end datetime);
    

    holidays.id 是假期的 ID,而不是员工的 ID。

    【讨论】:

    • Employee_ID 在 check_ins 表中,而不是在holidays 表中。将该表添加到原始选择中不会搞砸内部连接吗?假期表只定义假期,不向员工存储其他信息。
    • 当然employee_id在check_ins表中。 SQL 说ci_before.employee_id,其中ci_before 是别名check_ins。你一定是读错了SQL。请仔细查看 SQL 和 SQL fiddle!
    • 对不起,我还在学习更高级的东西。我有 SQL 功能(如,没有错误,但没有记录),但我真的不知道何时涉及 INNER JOIN。我知道我有前一天和后一天的记录,比如从 2​​013 年 11 月 27 日到 2013 年 11 月 30 日,假期表中的假期“感恩节”,但我从那个查询中得到零记录。感谢您的帮助!
    • 假期表有一个 ID 字段。您可以在分组前添加WHERE holiday.id = 2 以选择感恩节。如果它在你的情况下不起作用,请自己创建一个 SQL fiddle,我会看看。
    • 我是个需要睡觉的白痴。没关系,我知道出了什么问题。非常感谢您的意见,您的解决方案完美运行!
    【解决方案2】:

    你可以通过 php 在 2 个查询中完成,但你为什么要......这会很有趣!

    SELECT * FROM check_ins
        LEFT JOIN holidays AS holi_before 
            ON ( 
                datediff(holi_before.datetime_end,check_ins.datetime_end) <= 1
            )
        LEFT JOIN holidays AS holi_after
            ON (
                holi_before.id = holi_after.id 
                AND datediff(holi_after.datetime_end,check_ins.datetime_end) >= 1
            )
    

    应该可以做到(可能需要稍微调整 datediff 比较以使其完全正确。)

    还没有测试过,但我希望它能给你正确的推动:-)

    【讨论】:

    • 我应该更清楚。 check_ins 列 Employee_ID 是我需要的列。除此之外,我使用这个得到一个关于holy_before.Datefrom 的未知列: SELECT * FROM check_ins LEFT JOIN holiday AS Holi_before ON ( datediff(holy_before.Datefrom,Date(check_ins.ShiftStart_Datetime)) = 1 ) 感谢您的帮助! - 我已经编辑了原始问题。
    • 是一个错字,神圣而不是洒红节
    猜你喜欢
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 2021-10-24
    • 2020-06-11
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2016-01-08
    相关资源
    最近更新 更多