1

给定表格:

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

如何将这些查询重写为一个并返回所有必要的?

4

3 回答 3

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
于 2012-10-05T08:51:16.987 回答
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
于 2012-10-05T08:52:34.747 回答
1

这些查询可以使用联合组合在一起,但在联合中,所有查询必须返回相同的结果集,因为所有查询的输出必须相同。这可以按如下方式完成:

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
于 2012-10-05T09:00:51.523 回答