MySQL从具有公共ID的不同表中的日期获得给定日期的最近的未来日期

时间:2016-02-05 18:00:46

标签: 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           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。未来的日期:当前日期的CLOSEST或EQUAL,与相应的客户进一步相关,应按照所需结果中给出的格式进行过滤和排序

  
     

当前案例的CURDATE()是5.2.2016

失败:查询逻辑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

sqlfiddle

  

更新:要生成的更多结果是

     
    

2。客户端没有:DATED也应列出:可能带有NULL

         

3。 BANQUET表格中除DATED之外的其他信息也需要列出

  

更新所需结果

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

5 个答案:

答案 0 :(得分:2)

对于此查询,我建议您应用WHERE条件>= CURDATE(),然后SELECT应用MIN(dated) GROUP BY client_id

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:http://sqlfiddle.com/#!9/aded8/18

编辑反映新问题:

根据您添加的新信息 - 询问如何处理空值和“用餐”#39;专栏,我做了一些改变。此更新的查询处理过时的可能空值(通过调整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的答案结合起来,这听起来总体上会表现得更好。

新SQLFiddle:http://sqlfiddle.com/#!9/a4055/2

答案 1 :(得分:2)

一种方法使用相关子查询:

select c.*,
       (select max(dated)
        from banquet b
        where b.client_id = c.id and
              b.dated >= CURDATE()
       ) as dated
from client c;

然后,我会建议banquet(client_id, dated)上的索引。

这种方法的优点是性能。它不需要在整个客户端表上进行聚合。实际上,相关子查询可以利用索引,因此查询应该具有良好的性能。

答案 2 :(得分:1)

试试这个

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;

如果您想使用Client表连接,可以使用`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

答案 3 :(得分:1)

  

与当前日期相近或等于的日期

为了满足您的要求,我。即“CLOSEST”可能是当前日期之前或之后,查询必须使用它与DATED值之间的(绝对)差异。

所以可以这样实现:

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

以下是SQL fiddle

答案 4 :(得分:0)

尝试: ORDER BY(ABS(DATEDIFF(row_date,NOW()))AND row_date> = NOW())DESC