我读了许多关于只获得左连接的第一行的线程,但由于某种原因,这对我不起作用。
这是我的结构(当然简化)
订阅
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'
答案 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,您必须使用关键字LATERAL
在LEFT 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