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

Posted

技术标签:

【中文标题】MySQL从位于具有公共ID的不同表中的日期中获取最近的未来日期到给定日期【英文标题】:MySQL get the nearest future date to given date, from the dates located in different table having Common ID 【发布时间】:2016-02-05 18:00:46 【问题描述】:

我有两张桌子 - Client 和 Banquet

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. 未来的日期:接近或等于当前日期,与相应客户进一步相关的日期应按所需结果中给出的格式进行过滤和排序强>

当前案例的 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

UPDATE :要生成的进一步结果是这样的

2. 客户 WITHOUT : 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

【问题讨论】:

“饭”从何而来?鉴于您在回答问题后对问题进行了重大更改,您可能希望针对“NULL”案例和“膳食”组件发布一个单独的问题。 @Stidgeon 我也很困惑,我应该在同一个问题还是在新问题中问这个问题。但现在我认为新问题是一个好方法.. 【参考方案1】:

对于这个查询,我建议应用你的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

编辑以反映问题的新部分:

根据您添加的新信息 - 询问如何处理空值和“用餐”列,我进行了一些更改。此更新后的查询处理日期中可能的空值(通过调整 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

【讨论】:

它工作得很好,而且它还可以通过在SELECT 中提及来获取两个表中的任何字段。但它不能给CLIENTSBANQUET.DATED havin NULL。好吧,这不是我最初的问题,但我改进并更新了同样的问题。【参考方案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) 的索引。

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

【讨论】:

当只有banquet.dated 被作为banquet 的输出时,它的工作非常棒。但是,当我尝试为输出获取banquet.meal 时,它不起作用。好吧,这不是我最初的问题,但我更新了同样的问题。【参考方案3】:

试试这个

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,你可以使用`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

【讨论】:

【参考方案4】:

与当前日期最接近或等于的日期

为了密切响应您的要求,我。 e. “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

【讨论】:

@Stidgeon 是的,现在我明白了。但是问题已被修改,只是添加了“未来”(查看编辑 1),可能是当 OP 阅读我的答案并意识到问题不明确时。 @cFreed 这也不是我的确切问题,但它对我的其他查询有所帮助,因此支持答案【参考方案5】:

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

【讨论】:

为了让这个答案对这个问题的读者更有用,考虑添加一个描述来解释你在做什么。

以上是关于MySQL从位于具有公共ID的不同表中的日期中获取最近的未来日期到给定日期的主要内容,如果未能解决你的问题,请参考以下文章

从 laravel 的不同表中获取每个 id 的总数

Laravel:如何从具有关系的 3 个表中获取数据

从一个表中获取不同的行和*

从具有 SQLite 中的公共字段的数据库表中选择行

MySQL 从两个不同的表中获取 user_id 和密码的查询

是否有任何其他选项可以从表中获取总计数和同一查询中列的不同计数?