鉴于表格:
reservations (id, place_id, confirmed_at, paid_at)
和
places (id, name)
我需要返回可以分别表达以下查询的聚合:
-- Confirmed
SELECT places.id, places.name, COUNT(reservations.*) as total_confirmed
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.confirmed_at IS NOT NULL
GROUP BY places.id, places.name
-- Paid
SELECT places.id, places.name, COUNT(reservations.*) as total_paid
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.paid_at IS NOT NULL
GROUP BY places.id, places.name
-- Paid Uncofirmed
SELECT places.id, places.name, COUNT(reservations.*) as total_paid_unconfirmed
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.paid_at IS NOT NULL AND reservations.confirmed_at IS NULL
GROUP BY places.id, places.name
如何将这些查询重写为一个并返回所有必要的内容?
答案 0 :(得分:3)
SELECT places.id, places.name,
sum(case when (reservations.confirmed_at IS NOT NULL) then 1 else 0 end) as total_confirmed,
sum(case when (reservations.paid_at IS NOT NULL) then 1 else 0 end) as total_paid,
sum(case when (reservations.paid_at IS NOT NULL AND reservations.confirmed_at IS NULL) then 1 else 0 end) as total_confirmed_paid
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
GROUP BY places.id, places.name
答案 1 :(得分:1)
我更喜欢这样的查询,因为如果有一些places
尚未拥有reservation
或者可能已经有多个预订。仍然可以安全地计算SUM
。
SELECT d.*, a.total_confirmed, b.total_paid, c.total_paid_unconfirmed
FROM places d
LEFT JOIN
(
SELECT places.id, places.name, COUNT(reservations.*) as total_confirmed
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.confirmed_at IS NOT NULL
GROUP BY places.id, places.name
) a ON d.id = a.id
LEFT JOIN
(
SELECT places.id, places.name, COUNT(reservations.*) as total_paid
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.paid_at IS NOT NULL
GROUP BY places.id, places.name
) b ON d.id = b.id
LEFT JOIN
(
SELECT places.id, places.name, COUNT(reservations.*) as total_paid_unconfirmed
FROM reservations
INNER JOIN places ON places.id = reservations.place_id
WHERE
reservations.paid_at IS NOT NULL AND reservations.confirmed_at IS NULL
GROUP BY places.id, places.name
) c ON d.id = c.id
答案 2 :(得分:1)
这些查询可以使用union组合在一起,但在联合中,所有查询都必须返回相同的结果集,因为所有查询的输出必须相同。这可以按如下方式完成:
SELECT places.id, places.name,'total_confirmed' as totalType, COUNT(reservations.*) as total
FROM reservations INNER JOIN places ON places.id = reservations.place_id
WHERE reservations.confirmed_at IS NOT NULL
GROUP BY places.id, places.name
union all
SELECT places.id, places.name,'total_paid' as totalType, COUNT(reservations.*) as total
FROM reservations INNER JOIN places ON places.id = reservations.place_id
WHERE reservations.paid_at IS NOT NULL
GROUP BY places.id, places.name
union all
SELECT places.id, places.name,'total_paid_unconfirmed' as totalType, COUNT(reservations.*) as total
FROM reservations INNER JOIN places ON places.id = reservations.place_id
WHERE reservations.paid_at IS NOT NULL AND reservations.confirmed_at IS NULL
GROUP BY places.id, places.name