我的表是打印机列表。另一个表是服务日期列表(过去和将来)。
SELECT p.*, s.date AS service_date
FROM printer p
LEFT JOIN services s
ON s.printer = p.id
WHERE
s.date > NOW()
ORDER BY
service_date ASC
给我多行。我只希望列表中的下一个即将到来的日期。这意味着下一个服务日期。
您可以添加另一个JOIN
条件,该条件使用相关的子查询来确保您与正确的记录(即将来带有日期的第一个记录)一起加入:
SELECT p.*, s.date AS service_date
FROM printer p
LEFT JOIN services s
ON s.printer = p.id
AND s.date > NOW()
AND NOT EXISTS (
SELECT 1 FROM services s1
WHERE s1.printer = p.id
AND s1.date > NOW()
AND s1.date < s.date
)
ORDER BY service_date ASC
注意:由于您使用的是LEFT JOIN
,所以联接表上的所有条件都必须放在ON
的JOIN
子句中,而不是在WHERE
子句中(否则,您实际上是在执行INNER JOIN
)。我解决了。
处理此问题的标准方法是使用解析函数。假设您使用的是MySQL 8 +:
WITH cte AS (
SELECT p.*, s.date AS service_date,
ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY s.date DESC) rn
FROM printer p
LEFT JOIN services s ON s.printer = p.id
WHERE s.date > NOW()
)
SELECT *
FROM cte
WHERE rn = 1;
这将为每台打印机返回与最近服务日期相对应的记录。相反,如果我误解了并且您想要最旧的,请将调用中的ORDER BY
子句更改为上面的ROW_NUMBER
。