MySQL从单个表中列出一些字段,并从另一个表

时间:2015-10-26 02:59:46

标签: mysql subquery left-join inner-join

我的问题的主题有点令人困惑,因为我的语言不完整,以适应它的一般和技术描述。

从技术上讲,我特别想要完成的是:

  

列出所有教会及其相应的预订状态,并提供以下字段:

  • 教会ID AS id
  • 教会名称 AS name
  • 他们提供的所有服务的pending状态计数 AS pendingCount
  • 他们提供的所有服务的fully booked状态计数 AS bookedCount

关联表的结构如下:

教堂

+---------+---------------+
| 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

样本输出

enter image description here

3 个答案:

答案 0 :(得分:4)

我会使用条件聚合。这是一种对满足特定值的行进行求和的方法。在这种情况下,我们可以使用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,以便也不会返回没有任何预订的教会。

答案 1 :(得分:1)

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;

答案 2 :(得分:0)

尝试

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,