mySQL:查询,其中所有可能的值至少丢失一次

时间:2015-09-23 20:20:49

标签: mysql sql drupal

我有一个电视节目清单。每个电视节目可能会在0个或更多时区中变黑。要说一个节目被涂黑了"在时区中意味着网络无权在该时区播放节目。这些数据如下所示:

|----|---------------------|
| ID |         Show        |
|----|---------------------|
|  1 | Nightly News        |
|  2 | Primetime Sitcom    |
|  3 | Daytime Talkshow    |
|  4 | Nightly News II     |
|  5 | Daytime Talkshow II |
|  6 | Nightly News III    |
|----|---------------------|
   |
   |-----join
   |
   v
|----|----------------------|
| ID | Timezone Restriction |
|----|----------------------|
|  1 | EST                  |
|  1 | CST                  |
|  1 | PST                  |
|  2 | EST                  |
|  2 | CST                  |
|  3 | PST                  |
|  5 | CST                  |
|  5 | PST                  |
|  6 | HST                  |
|----|----------------------|

并非所有节目都受时区限制(大部分都不是)。根据这些数据,我需要获取一个包含所需数量的结果的列表,以便在每个时区中提供未被涂黑的2个节目。结果应按ID排序,每个时区都会看到尽可能低的无限制ID。

例如,在上面的数据集中,这个假设的查询将返回1-4行,例如:

|----|------------------|--------------|
| ID |       Show       | Restrictions |
|----|------------------|--------------|
|  1 | Nightly News     | EST,CST,PST  |
|  2 | Primetime Sitcom | EST,CST      |
|  3 | Daytime Talkshow | PST          |
|  4 | Nightly News II  | None         |
|----|------------------|--------------|

如您所见,在上面的结果集中,所有时区都至少有2个不受限制的节目。 EST或CST中的查看者可以观看节目3和4. PST中的查看者可以查看节目2和4.MST或HST中的查看者可以查看节目1和2.

我不能为我的生活找出能解决这个问题的SQL(旁注,我实际上并不需要在我的结果中使用"限制"列,&& #39; s就在这里是出于解释目的)。

2 个答案:

答案 0 :(得分:2)

创建一个列出所有时区的表格。然后,您可以使用节目列表CROSS JOIN来获取可以显示节目的所有潜在区域。然后使用带有限制表的LEFT JOIN来过滤掉符合任何限制的行,如Return row only if value doesn't exist中所述。

SELECT s.show, z.zone
FROM shows AS s
CROSS JOIN timezones AS z
LEFT JOIN restrictions AS r ON r.id = s.id AND r.`Timezone Restriction` = z.zone
WHERE r.id IS NULL
ORDER BY z.zone, s.id

DEMO

列出了每个时区中可以显示的所有节目,而不仅仅是前2个节目。请参阅Using LIMIT within GROUP BY to get N results per group?了解如何限制每个小组的结果数量。

答案 1 :(得分:0)

因此,考虑到这一点,我很确定我想做的事情是1)查找每个时区的无限制节目列表和2)UNION它们一起。这实际上看起来就像我现在想象的那样创建用例UNION

所以我可以获得单个时区无限制的节目:

SELECT `shows`.`ID`
FROM shows 
LEFT JOIN restrictions
ON `shows`.`ID`=`restrictions`.`ID`
AND `shows`.`ID` NOT IN (
  SELECT `restrictions`.`ID`
  FROM restrictions 
  WHERE `Timezone Restriction`='EST'
) 
LIMIT 2

然后将它们链接在一起如下:

(SELECT `shows`.`ID` FROM shows  LEFT JOIN restrictions  ON `shows`.`ID`=`restrictions`.`ID`  AND `shows`.`ID` NOT IN (select `restrictions`.`ID` from restrictions where `Timezone Restriction`='EST') LIMIT 2)
UNION
(SELECT `shows`.`ID` FROM shows  LEFT JOIN restrictions  ON `shows`.`ID`=`restrictions`.`ID`  AND `shows`.`ID` NOT IN (select `restrictions`.`ID` from restrictions where `Timezone Restriction`='CST') LIMIT 2)
UNION
(SELECT `shows`.`ID` FROM shows  LEFT JOIN restrictions  ON `shows`.`ID`=`restrictions`.`ID`  AND `shows`.`ID` NOT IN (select `restrictions`.`ID` from restrictions where `Timezone Restriction`='MST') LIMIT 2)
UNION
(SELECT `shows`.`ID` FROM shows  LEFT JOIN restrictions  ON `shows`.`ID`=`restrictions`.`ID`  AND `shows`.`ID` NOT IN (select `restrictions`.`ID` from restrictions where `Timezone Restriction`='PST') LIMIT 2)
UNION
(SELECT `shows`.`ID` FROM shows  LEFT JOIN restrictions  ON `shows`.`ID`=`restrictions`.`ID`  AND `shows`.`ID` NOT IN (select `restrictions`.`ID` from restrictions where `Timezone Restriction`='HST') LIMIT 2)
ORDER BY ID;

在所提供的sqlfiddle @Barmar之上构建:http://www.sqlfiddle.com/#!9/25773/1/0