我有两个表,A和B,A包含条目列表,B包含每个条目的多个状态行(0-n,按日期分组,状态0表示正常,1表示失败)。
现在我想从A中选择所有行及其最新状态和日期,以及最近的失败及其日期(失败定义为至少有一个条目为1)。
我尝试了两个左连接的东西,但我不相信它是最佳解决方案,并且仍然存在确定正确失败次数的问题(SUM(b2.status))
SELECT a.id, b1.date, SUM(b1.status), b2.date, SUM(b2.status) FROM tablea a
LEFT JOIN tableb b1 ON b1.aid=a.id
LEFT JOIN tableb b2 ON b2.aid=a.id
WHERE (b1.date=(SELECT MAX(`date`) FROM tableb WHERE aid=a.id) OR b1.date IS NULL)
AND (b2.date=(SELECT MAX(`date`) FROM tableb WHERE aid=a.id GROUP BY `date` HAVING SUM(`status`)>0) OR b2.date IS NULL)
GROUP BY a.id
答案 0 :(得分:0)
这样的事情应该有效。
SELECT a.id, b1.date status_date, b1.status, b2.date latest_failure,
(SELECT COUNT(*) FROM tableb WHERE aid = a.id AND status > 0) total_failures
FROM tablea a
LEFT JOIN tableb b1
ON b1.aid = a.id
AND b1.date = (SELECT MAX(date) FROM tableb WHERE aid = a.id)
LEFT JOIN tableb b2
ON b2.aid = a.id
AND b2.date = (SELECT MAX(date) FROM tableb WHERE aid = a.id AND status > 0)
这假设tableb.date字段是日期时间并且是唯一的。否则,您可能希望使用id字段。
答案 1 :(得分:0)
你也可以这样做。不确定哪一个更有效率。你可以尝试两种方式。
SELECT a.id, b1.date status_date, b1.status,
(SELECT MAX(date) FROM tableb WHERE aid = a.id AND status > 0) latest_failure,
(SELECT COUNT(*) FROM tableb WHERE aid = a.id AND status > 0) total_failures
FROM tablea a
LEFT JOIN tableb b1
ON b1.aid = a.id
AND b1.date = (SELECT MAX(date) FROM tableb WHERE aid = a.id)
答案 2 :(得分:0)
这应该有效。
SELECT a.id, MAX(b1.date) status_date, SUM(b1.status) latest_status,
(SELECT MAX(date) FROM tableb WHERE aid = a.id AND status > 0) latest_failure,
(SELECT COUNT(*) FROM tableb WHERE aid = a.id AND status > 0) total_failures
FROM tablea a
LEFT JOIN tableb b1
ON b1.aid = a.id
AND b1.date = (SELECT MAX(date) FROM tableb WHERE aid = a.id)
GROUP BY a.id;
如果您一天可能有多次失败,并希望将状态显示为“1”,请更改此信息:
SUM(b1.status)latest_status
到:
MAX(b1.status)latest_status。
答案 3 :(得分:0)
我不确定在一个非常大的数据库上性能如何,但它在较小的数据库上运行良好。
SELECT a.id, MAX(b1.date) status_date, SUM(b1.status) latest_status,
b2.date latest_failure,
b2.total_failures
FROM tablea a
LEFT JOIN tableb b1
ON b1.aid = a.id
AND b1.date = (SELECT MAX(date) FROM tableb WHERE aid = a.id)
LEFT JOIN
(SELECT aid, date, count(*) total_failures FROM tableb WHERE status > 0 GROUP BY aid, date) b2
ON b2.aid = a.id
AND b2.date = (SELECT MAX(date) FROM tableb WHERE aid = a.id AND status > 0)
GROUP BY a.id;