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
havin
NULL
。这不是我最初的问题,但我改进并更新了同样的问题。“饭”是从哪里来的?鉴于您在回答问题后对问题进行了重大更改,您可能希望为“空”案例和“膳食”组件发布一个单独的问题。@Stidgeon我也很困惑,我应该在同一个问题中还是在新问题中问这个问题。但现在我觉得新问题是个好办法。@Stidgeon是的,现在我明白了。但问题已被修改,只是添加了“未来”(参见编辑1),可能是在OP阅读我的答案并意识到该问题模棱两可时。@cFreed这也不是我的确切问题,但它对我的另一个问题有帮助,因此对回答者进行了投票,使该答案对该问题的读者更有用,考虑添加描述来解释你在做什么。