在日期和小于日期之间左联接
Left Join Between Dates and Less Than
我有以下选择查询
$sql="SELECT s1.*
FROM schedulelocation s1
LEFT JOIN schedulelocation s2
ON (s1.uid=s2.uid AND s1.stp>s2.stp)
WHERE s2.stp is NULL AND s1.uid=:s1_uid AND s1.thu=:s1_thu AND s1.start<=:s1_start AND s1.end>=:s1_end";
这是我的 schedulelocation 数据(简化版)
UID STP start end Mon Tue Thu Comment
T5632 P 2015-10-06 2015-11-05 1 1 1 Hello
U4123 P 2015-09-05 2015-10-09 1 1 1 Apple
T5632 O 2015-10-06 2015-10-10 1 1 1 Pear
U4123 O 2015-10-29 2015-10-31 1 1 1 Orange
假设日期是 2015-10-08 我希望从查询中得到以下答案
对于 uid T5632 的答案 "Pear"
对于 uid T4123,答案 "Apple"
ie 查询应检查所选日期(即 2015-10-08)是否位于 table 中的开始日期和结束日期之间,然后选择最低的字母表 "stp" . (它还必须确保这一天是星期四)
查询成功找到 Pear 但没有找到 uid T4123 的结果
U4123
的答案"Apple"你能帮我吗
编辑 - 我现在已经尝试 GROUP BY
$sql="SELECT * FROM (SELECT * FROM schedulelocation WHERE thu=:thu AND start<=:start AND end>=:end ORDER BY stp ) AS cifstp GROUP BY uid ";
您可以使用 ORDER BY 和 LIMIT 1,无需连接:
SELECT s1.*
FROM
schedulelocation s1
WHERE
s1.uid=:s1_uid AND s1.thu=:s1_thu
AND s1.start<=:s1_start AND s1.end>=:s1_end
ORDER BY
stp
LIMIT 1
请看一个fiddle here.
编辑
如果您想 运行 单个查询,是的,您需要使用 SELF JOIN。您的查询的问题是您必须在 JOIN 条件中添加所选日期的检查:
SELECT s1.*
FROM
schedulelocation s1 LEFT JOIN schedulelocation s2
ON s1.uid=s2.uid
AND s1.thu=s2.thu
AND :datea BETWEEN s2.start AND s2.end
AND s1.STP>s2.STP
WHERE
:dateb BETWEEN s1.start AND s1.end
AND s1.thu=:thu
AND s2.uid IS NULL
请看here.
有点调皮,但是你可以在字符串上使用MAX()
和MIN()
...
(这应该比您的子查询解决方案更快。使用 EXPLAIN
检查。)
SELECT
s1.*,
MIN(Comment)
FROM schedule location AS s1
WHERE
thu = 1 AND
start <= '2015-10-08' AND
end >= '2015-10-08'
GROUP BY
uid
我有以下选择查询
$sql="SELECT s1.*
FROM schedulelocation s1
LEFT JOIN schedulelocation s2
ON (s1.uid=s2.uid AND s1.stp>s2.stp)
WHERE s2.stp is NULL AND s1.uid=:s1_uid AND s1.thu=:s1_thu AND s1.start<=:s1_start AND s1.end>=:s1_end";
这是我的 schedulelocation 数据(简化版)
UID STP start end Mon Tue Thu Comment
T5632 P 2015-10-06 2015-11-05 1 1 1 Hello
U4123 P 2015-09-05 2015-10-09 1 1 1 Apple
T5632 O 2015-10-06 2015-10-10 1 1 1 Pear
U4123 O 2015-10-29 2015-10-31 1 1 1 Orange
假设日期是 2015-10-08 我希望从查询中得到以下答案
对于 uid T5632 的答案 "Pear" 对于 uid T4123,答案 "Apple"
ie 查询应检查所选日期(即 2015-10-08)是否位于 table 中的开始日期和结束日期之间,然后选择最低的字母表 "stp" . (它还必须确保这一天是星期四)
查询成功找到 Pear 但没有找到 uid T4123 的结果
U4123
的答案"Apple"你能帮我吗编辑 - 我现在已经尝试 GROUP BY
$sql="SELECT * FROM (SELECT * FROM schedulelocation WHERE thu=:thu AND start<=:start AND end>=:end ORDER BY stp ) AS cifstp GROUP BY uid ";
您可以使用 ORDER BY 和 LIMIT 1,无需连接:
SELECT s1.*
FROM
schedulelocation s1
WHERE
s1.uid=:s1_uid AND s1.thu=:s1_thu
AND s1.start<=:s1_start AND s1.end>=:s1_end
ORDER BY
stp
LIMIT 1
请看一个fiddle here.
编辑
如果您想 运行 单个查询,是的,您需要使用 SELF JOIN。您的查询的问题是您必须在 JOIN 条件中添加所选日期的检查:
SELECT s1.*
FROM
schedulelocation s1 LEFT JOIN schedulelocation s2
ON s1.uid=s2.uid
AND s1.thu=s2.thu
AND :datea BETWEEN s2.start AND s2.end
AND s1.STP>s2.STP
WHERE
:dateb BETWEEN s1.start AND s1.end
AND s1.thu=:thu
AND s2.uid IS NULL
请看here.
有点调皮,但是你可以在字符串上使用MAX()
和MIN()
...
(这应该比您的子查询解决方案更快。使用 EXPLAIN
检查。)
SELECT
s1.*,
MIN(Comment)
FROM schedule location AS s1
WHERE
thu = 1 AND
start <= '2015-10-08' AND
end >= '2015-10-08'
GROUP BY
uid