MySQL从位于具有公共ID的不同表中的日期中获取距离给定日期最近的未来日期
我有两张桌子——客人桌和宴会桌MySQL从位于具有公共ID的不同表中的日期中获取距离给定日期最近的未来日期,mysql,sql,join,Mysql,Sql,Join,我有两张桌子——客人桌和宴会桌 Client Table ---------------------------- ID NAME 1 John 2 Jigar 3 Jiten ---------------------------- Banquet Table ---------------------------- ID CLIENT_ID DATED 1 1 2016.2.3 2 2
Client Table
----------------------------
ID NAME
1 John
2 Jigar
3 Jiten
----------------------------
Banquet Table
----------------------------
ID CLIENT_ID DATED
1 1 2016.2.3
2 2 2016.2.5
3 2 2016.2.8
4 3 2016.2.6
5 1 2016.2.9
6 2 2016.2.5
7 2 2016.2.8
8 3 2016.2.6
9 1 2016.2.7
----------------------------
:::::::::: **Required Result**
----------------------------
ID NAME DATED
2 Jigar 2016.2.5
3 Jiten 2016.2.6
1 John 2016.2.7
生成的结果如下所示:
1.未来日期:与当前日期最接近或相等的日期,应按照所需结果中给出的格式进行过滤和排序
ID NAME DATED MEAL
2 Jigar 2016.2.5 lunch
3 Jiten 2016.2.6 breakfast
1 John 2016.2.7 dinner
4 Junior - -
5 Master - supper
当前病例的CURDATE()为2016年2月5日
失败:查询逻辑1
SELECT c.id, c.name, b.dated
FROM client AS c, banquet AS b
WHERE c.id = b.client_id AND b.dated >= CURDATE()
ORDER BY (b.dated - CURDATE());
------------------------------------------- OUTPUT
ID NAME DATED
2 Jigar 2016.2.5
2 Jigar 2016.2.5
3 Jiten 2016.2.6
3 Jiten 2016.2.6
1 John 2016.2.7
2 Jigar 2016.2.8
2 Jigar 2016.2.8
1 John 2016.2.9
失败:查询逻辑2
SELECT c.id, c.name, b.dated
FROM client AS c, banquet AS b
WHERE b.dated = (
SELECT MIN(b.dated)
FROM banquet as b
WHERE b.client_id = c.id
AND b.dated >= CURDATE()
)
ORDER BY (b.dated - CURDATE());
------------------------------------------- OUTPUT
ID NAME DATED
2 Jigar 2016.2.5
2 Jigar 2016.2.5
3 Jiten 2016.2.6
3 Jiten 2016.2.6
1 John 2016.2.7
更新:要生成的进一步结果如下
2.不带日期的客户机也应列出:可能为空
3.宴会桌上除注明日期外的其他信息也需要列出
更新所需结果
ID NAME DATED MEAL
2 Jigar 2016.2.5 lunch
3 Jiten 2016.2.6 breakfast
1 John 2016.2.7 dinner
4 Junior - -
5 Master - supper
对于此查询,我建议应用您的
WHERE
条件>=CURDATE()
,然后使用按客户id分组选择MIN(dated)
:
SELECT b.client_id, MIN(b.dated) FROM banquet b
WHERE b.dated >= CURDATE()
GROUP BY b.client_id;
由此,您可以向客户机表中添加必要的JOIN
,以获取客户机名称:
SELECT b.client_id, c.name, MIN(b.dated) FROM banquet b
INNER JOIN client c
ON c.id = b.client_id
WHERE b.dated >= CURDATE()
GROUP BY b.client_id;
SQLFiddle:
编辑以反映问题的新部分:
根据您添加的新信息——询问如何处理空值和“用餐”列,我做了一些更改。此更新的查询处理日期中可能的空值(通过调整WHERE子句),还包括用餐信息
SELECT b.client_id, c.name,
MIN(b.dated) AS dated,
IFNULL(b.meal, '-') AS meal
FROM banquet b
INNER JOIN client c
ON c.id = b.client_id
WHERE b.dated >= CURDATE() OR b.dated IS NULL
GROUP BY b.client_id;
或者你也可以把它和Gordon Linoff的答案结合起来,听起来总体上会表现得更好
新建SQLFIDLE:试试这个
SELECT banquet.client_id, MIN(banquet.dated)
FROM banquet
WHERE banquet.dated >= CURDATE()
GROUP BY banquet.client_id;
如果希望限制输出,如预期结果为3条记录,则在本例中可以使用limit
SELECT banquet.client_id, MIN(banquet.dated)
FROM banquet
WHERE banquet.dated >= CURDATE()
GROUP BY banquet.client_id limit 3;
如果要将join与客户机
表一起使用,可以使用“join”
SELECT banquet.client_id, MIN(banquet.dated)
FROM banquet JOIN Client
ON Client.id = banquet.client_id
WHERE banquet.dated >= CURDATE()
GROUP BY banquet.client_id;
在最后一次查询中也使用limit
。一种方法使用相关子查询:
select c.*,
(select max(dated)
from banquet b
where b.client_id = c.id and
b.dated >= CURDATE()
) as dated
from client c;
然后,我建议在宴会(客户id,日期)
上建立一个索引
这种方法的优点是性能。它不需要对整个客户机表进行聚合。事实上,相关子查询可以利用索引,因此查询应该具有良好的性能
最接近或等于当前日期的日期
为了符合您的要求,我。E“最近”可能在当前日期之前或之后,查询必须使用它与日期之间的(绝对)差值
所以可以这样实现:
SELECT
c.id, c.name, b.dated,
MIN(ABS(TIMESTAMPDIFF(DAY, b.dated, CURDATE()))) AS `delta`
FROM banquet AS b
INNER JOIN client AS c ON b.client_id = c.id
GROUP BY b.client_id
以下是试一试:
ORDER BY(ABS(DATEDIFF(row_date,NOW())和row_date>=NOW())描述其工作原理,当只有宴会。日期作为宴会的输出时。但是,当我试图获得宴会.餐点
时,输出也不起作用。嗯,这不是我最初的问题,但我更新了问题。它工作得很好,而且通过在选择中提及,它还可以从两个表中获取任何字段。但它不能给客户提供宴会.DATED
havinNULL
。这不是我最初的问题,但我改进并更新了同样的问题。“饭”是从哪里来的?鉴于您在回答问题后对问题进行了重大更改,您可能希望为“空”案例和“膳食”组件发布一个单独的问题。@Stidgeon我也很困惑,我应该在同一个问题中还是在新问题中问这个问题。但现在我觉得新问题是个好办法。@Stidgeon是的,现在我明白了。但问题已被修改,只是添加了“未来”(参见编辑1),可能是在OP阅读我的答案并意识到该问题模棱两可时。@cFreed这也不是我的确切问题,但它对我的另一个问题有帮助,因此对回答者进行了投票,使该答案对该问题的读者更有用,考虑添加描述来解释你在做什么。