LEFT JOINed 表的 SQL 限制

Posted

技术标签:

【中文标题】LEFT JOINed 表的 SQL 限制【英文标题】:SQL limit for LEFT JOINed table 【发布时间】:2012-12-17 13:07:39 【问题描述】:

我有以下表格。

    行业(ID、名称) Movie(id, name, industry_id) [行业有很多电影] Trailer(id, name, movie_id) [电影有很多预告片]

我需要为每个行业找到 6 个最新预告片。每部电影不需要有预告片,也可以有多个[0-n]。

CREATE TABLE industry(id int, name char(10), PRIMARY KEY (id));

CREATE TABLE movie(id int, name char(10), industry_id int, PRIMARY KEY (id),
FOREIGN KEY (industry_id) REFERENCES industry(id));

CREATE TABLE trailer(id int, name char(10), movie_id int, PRIMARY KEY (id),
FOREIGN KEY (movie_id) REFERENCES movie(id));

INSERT INTO industry VALUES (1, "sandalwood");
INSERT INTO industry VALUES (2, "kollywood");

INSERT INTO movie VALUES (1, "lakshmi", 1);
INSERT INTO movie VALUES (2, "saarathi", 2);

INSERT INTO trailer VALUES (1, "lakshmi1", 1);
INSERT INTO trailer VALUES (2, "lakshmi2", 1);
INSERT INTO trailer VALUES (3, "lakshmi3", 1);
INSERT INTO trailer VALUES (4, "lakshmi4", 1);
INSERT INTO trailer VALUES (5, "lakshmi5", 1);
INSERT INTO trailer VALUES (6, "lakshmi6", 1);

INSERT INTO trailer VALUES (7, "saarathi4", 2);
INSERT INTO trailer VALUES (8, "saarathi5", 2);
INSERT INTO trailer VALUES (9, "saarathi6", 2);

SELECT  c.*
FROM    industry a
        LEFT JOIN movie b
            ON a.id = b.industry_id
        LEFT JOIN trailer c
            ON b.id = c.movie_id
LIMIT 0, 6

| ID |     NAME | MOVIE_ID |
----------------------------
|  1 | lakshmi1 |        1 |
|  2 | lakshmi2 |        1 |
|  3 | lakshmi3 |        1 |
|  4 | lakshmi4 |        1 |
|  5 | lakshmi5 |        1 |
|  6 | lakshmi6 |        1 |

我只需要从每部电影中获取一个最近的预告片。但我得到了每部电影的所有预告片。请建议我获取SQL 声明。

【问题讨论】:

您想要每部电影的最后预告片吗?我说的对吗? 【参考方案1】:

如果您想要 trailer 表的 id 的最新预告片,请使用以下查询:

SELECT * FROM trailer t 
INNER JOIN (SELECT movie_id, MAX(id) id 
            FROM trailer GROUP BY movie_id) AS A ON t.id = A.id 

如果您想要按日期最新的数据,请使用此查询:

SELECT * FROM trailer t 
INNER JOIN (SELECT movie_id, MAX(latestbydate) latestbydate 
            FROM trailer GROUP BY movie_id
           ) AS A ON t.movie_id = A.movie_id  AND t.latestbydate = A.latestbydate

【讨论】:

【参考方案2】:
SELECT i.name, m.name, MAX(t.id) AS 'Latest Trailer ID', MAX(t.name) AS 'Latest Trailer'    
FROM industry i
INNER JOIN movie m ON(i.id = m.industry_id)
INNER JOIN trailer t ON(m.id = movie_id)
GROUP BY m.id

【讨论】:

【参考方案3】:

试试这个查询

SELECT * FROM industry
LEFT JOIN movie on movie.industry_id = industry.id
LEFT JOIN (
  SELECT 
  id as T_ID,
  name as T_Name,
  movie_id
  FROM trailer 
  INNER JOIN ( SELECT 
              MAX(id) as TID
              FROM trailer
              GROUP BY movie_id
             ) as t on t.TID = trailer.id
) as c on c.movie_id = movie.id;

这里是Demo

【讨论】:

【参考方案4】:

如果您必须在 SQL 中完成这一切(而不是在您使用的任何后端或代码中,我实际上会推荐),那么您可能不得不依赖一些变量魔法。

基本上,您需要按日期对每个预告片进行“排名”,然后按预告片所属的电影对其进行“分区”。这些词在其他一些 SQL 风格中具有实际意义(例如PL/SQL),但不幸的是在 mysql 中没有本机功能。

你会想要做类似于this SO post 中提到的事情。一旦你得到按movie_id划分的“等级”,你只需选择WHERE rank < 6。查询可能会变得非常混乱,并且以这种方式使用变量存在一些风险,但据我所知,这是严格使用 MySQL 查询的最佳方法

【讨论】:

不,这个查询没有那么棘手。不需要分区/排名。 如果他想获得每部电影的 6 个最新预告片?我在这里看到的其他所有内容都只是最新的,不是吗? 您在哪里看到他需要最新的 6 个?我读到他需要“只从每部电影中获取一个最近的预告片”。 @Brandon 哈哈 帖子的第二行,“我需要为每个行业找到 6 个最新的预告片。”但你是对的,后来他似乎改变了主意...... 其实他并没有改变主意。我只是忽略了那部分,而你忽略了我关注的部分。它们并不相互排斥,因为他说他需要每部电影的最新预告片,但需要每个行业的 6 个最新预告片。【参考方案5】:

我不确定这是否适用于 MySql,因为我不记得您是否可以在 in 子句中包含子查询,但您可以尝试:

select * from trailer
where id in (select max(id) from trailer group by movie_id)

无论它是否有效,您似乎没有在查询中使用行业表,因此加入它没有多大意义(除非您实际上试图排除没有分配任何行业的电影他们......但根据你的样本,我看起来不是你的意图)。

如果上面的查询在MySql中不起作用,那么试试这个

select  t.* 
from    trailer t join
        (select max(id) id from trailer group by movie_id) t2 on t1.id = t2.id

【讨论】:

另外,我假设预告片表中较高的 id 是较新的。但最好像 Tarika 建议的那样实际设置一个日期列。【参考方案6】:

要获取最近的跟踪,您应该包含我们可以从中获取它的日期字段列

【讨论】:

我不知道是谁投了反对票,但这是个好建议。 @Brandon:我同意,你不能指望在没有日期时间列的情况下查询“最新”。

以上是关于LEFT JOINed 表的 SQL 限制的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 双表 INNER JOIN , LEFT JOINED 到第三张表,只有一行具有最低值

MySQL # left join 语句,对右表的限制条件使用注意问题

sql中的inner join ,left join ,right join

如何将 LEFT JOIN 限制为 SQL Server 中的第一个结果?

Oracle左连接右连接全外连接以及(+)号用法

为啥批量收集到子句限制了 pl/sql 中嵌套表的大小