MySQL 列出来自单个 table 的一些字段并计算来自另一个 table 的所有特定字段引用

MySQL List some field from a single table and COUNT all particular field reference from another table

我的问题的主题有点令人困惑,因为我运行无法用适合它的一般和技术描述的词来表达。

用不太专业的术语来说,我要具体完成的是:

List all churches and their corresponding booking status from a service they are offering with the following fields:

关联表结构如下:

教堂

+---------+---------------+
| id(int) | name(varchar) |
+---------+---------------+

服务

+---------+---------------+---------------+
| id(int) | name(varchar) | churchId(int) |
+---------+---------------+---------------+

预订

+---------+-----------------+----------------+
| id(int) | status(varchar) | serviceId(int) |
+---------+-----------------+----------------+

到目前为止我得到的是这个,我完全不知道为什么它正在编译但会产生负面结果:

SELECT
    churches.id,
    churches.name,
    pending.count AS pendingCount,
    booked.count AS bookedCount
FROM
    churches
INNER JOIN
    services
ON
    services.churchId = churches.id
LEFT JOIN
    (SELECT
        COUNT(bookings.id) AS `count`,
        bookings.serviceId
     FROM
        bookings
     WHERE
        bookings.status = 'pending'
     GROUP BY
        bookings.serviceId)
     AS pending
ON
    pending.serviceId = services.id
LEFT JOIN
    (SELECT
        COUNT(bookings.id) AS `count`,
        bookings.serviceId
     FROM
        bookings
     WHERE
        bookings.status = 'fully booked'
     GROUP BY
        bookings.serviceId)
     AS booked
ON
    booked.serviceId = services.id

示例输出

我会为此使用条件聚合。这是一种对满足特定值的行数求和的方法。在这种情况下,我们可以对 SUM(b.status = 'fullyBooked')SUM(b.status = 'pending') 使用聚合,并按教会 id 分组,如下所示:

SELECT c.id, c.name,
    SUM(b.status = 'pending') AS pendingCount,
    SUM(b.status = 'fully booked') AS bookedCount
FROM bookings b
RIGHT JOIN services s ON s.id = b.serviceId
RIGHT JOIN churches c ON c.id = s.churchid
GROUP BY c.id;

重申一下,通过使用 SUM(condition) 并按某个 id 值分组,您计算的是该 id 值的条件成立的次数。


编辑:

我已将 RIGHT OUTER JOIN 添加到此查询中,以便返回没有任何预订的教堂。

尝试

SELECT
    churches.id,
    churches.name,
    count(case when bookings.status = 'pending' then 1 else null end) AS pendingCount,
    count(case when bookings.status = 'fully booked' then 1 else null end) AS bookedCount
FROM
    churches
INNER JOIN
    services
ON
    services.churchId = churches.id
LEFT JOIN bookings on bookings.serviceId=services.id
group by 
    churches.id,
    churches.name,
select c.id, c.name,
       SUM(b.status = 'pending') pendingCount,
       SUM(b.status = 'fully booked') bookedCount
from   church c
-- Left join here if you want all churches whether or not they offer a service
left join services s on (c.id = s.churchId)
-- Left join here if you want all churches w/ a service, but may have no bookings
left join bookings b on (s.id = b.serviceId)
group by c.id, c.name;