SQL使用子查询

时间:2017-04-27 10:53:36

标签: mysql sql

我想为特定活动制作一个这样的清单,目前报名的志愿者数量低于所需数量。我正在使用MySQL:

Volunteer Role
==============
Stewarding
Video

(急救没有出现,因为已经有2人签约了这个团队)

我的表格是:

Delegate
========
OrderId   Name      volunteerOption
1         Tim       
1         Jane      First Aid
1         Mary      First Aid
1         Jo        Stearding


VolunteerRole
===========
eventId   volunteerName   quantityNeeded
1         First Aid       2
1         Stewarding      10


Orders
======
Id        eventId
1         1

Event
=====
id      name
1       Fun Run

我认为我需要使用带有连接的子查询,但我不确定如何链接它们。

我的两个问题是:

SELECT roleName, quantity as size
FROM VolunteerRole
WHERE eventId = 1

这给了我团队名称和最大尺寸

SELECT DISTINCT count(volunteerOption) as volunteers, volunteerOption
FROM delegate
JOIN orders on delegate.orderId = orders.id
WHERE orders.eventId = 1 and volunteerOption <> '' 
GROUP BY volunteerOption

这给了我每个团队目前的志愿者数量。我无法弄清楚的是如何只选择志愿者数量少于最大值的团队。

感激不尽的任何帮助

4 个答案:

答案 0 :(得分:1)

请尝试以下方法......

SELECT volunteerName AS 'Volunteer Role'
FROM ( SELECT volunteerName AS volunteerName,
              quantityNeeded AS quantityNeeded,
              COUNT( volunteerOption ) AS volunteersCount
       FROM Delegate
       JOIN Orders ON Delegate.OrderId = Orders.Id
       RIGHT JOIN VolunteerRole ON Orders.eventId = VolunteerRole.eventId
                               AND Delegate.volunteerOption = VolunteerRole.volunteerName
       WHERE Orders.eventId = 1
       GROUP BY volunteerName,
                quantityNeeded
     ) AS volunteersCountFinder
WHERE quantityNeeded > volunteersCount
GROUP BY volunteerName;

此声明首先在INNER JOINDelegate之间执行Orders,向我们提供分配给每个订单以及每个事件的代理列表。

然后将此列表右键加入VolunteerRole,为我们提供分配给该事件中每个事件的每个角色的代表列表。执行RIGHT JOIN而不是INNER JOIN,以便即使没有分配代理,仍会列出事件中的角色。

请注意,RIGHT JOINLEFT JOIN大致相同。您使用的是由JOIN的哪一侧具有应保留不匹配记录的表格。

然后,通过eventId子句将两个联接生成的数据集细化为1 WHERE的记录。

然后,精炼数据集按volunteerName分组。按quantityNeeded进行分组不能有效地优化或扩大volunteerName分组,因为volunteerName的每个值只有quantityNeeded的一个对应值,但GROUP BY要求您可以使用聚合函数未生成的所有字段进行分组。

然后计算NULL的每个非volunteerOption值的计数。 COUNT()将返回0,其中角色未分配任何代理,即NULL值遇到NULL而非volunteerOption的值volunteerName 在这里与volunteerName混淆,每个记录中都会有一个值。

子查询然后返回一个列表,其中包含每个quantityNeeded及其对应的volunteersCountvolunteerName(给予我们计数的别名)。

主查询然后将子查询的数据集精确到那些所需数量大于分配的志愿者数量的数据集,并将结果按volunteerName进行分组。然后,语句将返回此组中SELECT eventId, volunteerName AS 'Volunteer Role' FROM ( SELECT Orders.eventId AS eventId, volunteerName AS volunteerName, quantityNeeded AS quantityNeeded, COUNT( volunteerOption ) AS volunteersCount FROM Delegate JOIN Orders ON Delegate.OrderId = Orders.Id RIGHT JOIN VolunteerRole ON Orders.eventId = VolunteerRole.eventId AND Delegate.volunteerOption = VolunteerRole.volunteerName GROUP BY Orders.eventId, volunteerName, quantityNeeded ) AS volunteersCountFinder WHERE quantityNeeded > volunteersCount GROUP BY eventId, volunteerName; 的每个值。

如果您有任何问题或意见,请随时发表评论。

附录

如果您希望扩展此声明以列出所有角色填充不充分的事件以及每个未充分填充的角色,您可以使用...

while

答案 1 :(得分:0)

这可以在任何需要的地方为您提供event_id,order_id,employee_type,employee_needed:

SELECT a.id as event_id, b.id as order_id, d.volunteerOption, c.quantityNeeded-d.employeed as still_to_find
FROM events a
LEFT JOIN orders b ON a.id=b.eventId
LEFT JOIN VolunteerRole c ON a.id=c.eventId
LEFT JOIN (SELECT order_id, volunteerOption, COUNT(*) as employeed FROM Delegate WHERE volunteerOption IS NOT NULL GROUP BY order_id, volunteerOption) d ON b.id=d.order_id AND c.volunteerName=d.volunteerOption
WHERE c.quantityNeeded<d.employeed 

答案 2 :(得分:0)

我认为您必须分两步执行此操作,因为您无法检查聚合值与非聚合值

select  distinct volunteerName
from    (
            SELECT  t1.volunteerName, t1.quantityNeeded, count(t2.Name) as cnt
            FROM    VolunteerRole t1
            JOIN    Orders t2
            ON      t1.eventId = t2.eventId
            LEFT JOIN
                    Delegate t3
            ON      t1.VolunteerName = t3.volunteerOption and
                    t2.Id = t3.OrderId
            WHERE   t1.eventId = 1
        ) t1
where   quantityNeeded > cnt

答案 3 :(得分:0)

尝试此查询。这应该可以正常工作

select  distinct volunteerName from (SELECT  t1.volunteerName, t1.quantityNeeded, count(t2.Name) as cnt FROM    VolunteerRole t1 JOIN    Orders t2 ON      t1.eventId = t2.eventId
LEFT JOIN Delegate t3 ON t1.VolunteerName = t3.volunteerOption and t2.Id = t3.OrderId WHERE   t1.eventId = 1
 ) t1 where   quantityNeeded > cnt;