LEFT JOIN仅第一行

时间:2013-03-25 23:06:12

标签: mysql join left-join

我读了许多关于只获得左连接的第一行的线程,但由于某种原因,这对我不起作用。

这是我的结构(当然简化)

订阅

id |  title | content
----------------------
1  | Feed 1 | ...

艺术家

artist_id | artist_name
-----------------------
1         | Artist 1
2         | Artist 2

feeds_artists

rel_id | artist_id | feed_id
----------------------------
1      |     1     |    1 
2      |     2     |    1 
...

现在我想收到文章并加入第一位艺术家,我想到了这样的事情:

SELECT *
    FROM feeds 
    LEFT JOIN feeds_artists ON wp_feeds.id = (
        SELECT feeds_artists.feed_id FROM feeds_artists
        WHERE feeds_artists.feed_id = feeds.id 
    LIMIT 1
    )
WHERE feeds.id = '13815'

只是为了获取feed_artists的第一行,但这已经无效了。

由于我的数据库,我无法使用TOP而我无法按feeds_artists.artist_id对结果进行分组,因为我需要按日期对它们进行排序(我通过这种方式对结果进行分组,但是结果哪里不是最新的)

尝试使用OUTER APPLY也是如此 - 也没有成功。 说实话,我无法想象这些行中会发生什么 - 可能是我无法让它发挥作用的最大原因。

解决方案:

SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
    SELECT artist_id
    FROM feeds_artists fa 
    WHERE fa.feed_id = f.id
    LIMIT 1
)
WHERE f.id = '13815'

8 个答案:

答案 0 :(得分:88)

如果您可以假设艺术家ID会随着时间的推移而增加,那么MIN(artist_id)将是最早的。

所以尝试这样的事情(未经测试......)

SELECT *
  FROM feeds f
  LEFT JOIN artists a ON a.artist_id = (
    SELECT
      MIN(fa.artist_id) a_id
    FROM feeds_artists fa 
    WHERE fa.feed_id = f.feed_id
  ) a

答案 1 :(得分:51)

没有子选择的版本:

   SELECT f.title,
          f.content,
          MIN(a.artist_name) artist_name
     FROM feeds f
LEFT JOIN feeds_artists fa ON fa.feed_id = f.id
LEFT JOIN artists a ON fa.artist_id = a.artist_id
 GROUP BY f.id

答案 2 :(得分:9)

@Matt Dodges的回答使我步入正轨。再次感谢您提供所有答案,在此期间,这对很多人都有所帮助。像这样工作:

SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
    SELECT artist_id
    FROM feeds_artists fa 
    WHERE fa.feed_id = f.id
    LIMIT 1
)
WHERE f.id = '13815'

答案 3 :(得分:3)

基于这里的几个答案,我发现了一些对我有用的东西,我想归纳并解释正在发生的事情。

转换:

LEFT JOIN table2 t2 ON (t2.thing = t1.thing)

收件人:

LEFT JOIN table2 t2 ON (t2.p_key = (SELECT MIN(t2_.p_key) 
    FROM table2 t2_ WHERE (t2_.thing = t1.thing) LIMIT 1))

连接t1和t2的条件从ON移到内部查询WHERE中。 MIN(primary key)LIMIT 1确保内部查询只返回1行。

在选择特定行之后,我们需要告诉ON它是哪一行。这就是ON比较连接表的主键的原因。

您可以使用内部查询(即order + limit),但它必须返回所需行的一个主键,该主键将告诉ON要加入的确切行。

答案 4 :(得分:2)

我已经使用了其他东西(我认为更好......)并希望分享它:

我创建了一个包含"组"的视图。条款

CREATE VIEW vCountries AS SELECT * PROVINCES GROUP BY country_code

SELECT * FROM client INNER JOIN vCountries on client_province = province_id

我想说,我认为我们需要做这个解决方案,因为我们在分析中有些错误...至少在我的情况下......但有时这样做会更便宜重新设计一切...

我希望它有所帮助!

答案 5 :(得分:1)

我想给出一个更普遍的答案。当您只想选择LEFT JOIN中的第一项时,它将处理任何情况。

您可以使用一个子查询来查询GROUP_CONCATS想要的内容(也进行排序!),然后仅拆分GROUP_CONCAT的结果,并只取其第一项,就像这样...

LEFT JOIN Person ON Person.id = (
    SELECT SUBSTRING_INDEX(
        GROUP_CONCAT(FirstName ORDER BY FirstName DESC SEPARATOR "_" ), '_', 1)
    ) FROM Person
);

由于我们将 DESC 作为我们的 ORDER BY 选项,因此将返回“ Zack”之类的人员ID。如果我们想要一个名字像“ Andy”的人,我们可以将 ORDER BY FirstName DESC 更改为 ORDER BY FirstName ASC

这很灵活,因为这使订购的力量完全掌握在您的手中。但是,经过大量测试,在有大量用户和大量数据的情况下,它无法很好地扩展

但是,它对于为管理员运行数据密集型报告很有用。

答案 6 :(得分:0)

这是我使用group by子句的答案。

Contents/MacOS/Resources/lib

答案 7 :(得分:0)

对于某些数据库,例如DB2和PostgreSQL,您必须使用关键字LATERALLEFT JOIN中指定子查询:(这里,它用于DB2)

SELECT f.*, a.*
FROM feeds f
LEFT JOIN LATERAL  
(
    SELECT artist_id, feed_id
    FROM feeds_artists sfa
    WHERE sfa.feed_id = f.id
    fetch first 1 rows only
) fa ON fa.feed_id = f.id
LEFT JOIN artists a ON a.artist_id = fa.artist_id