左连接只有第一行

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

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

喂食

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

艺术家

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

饲料 _ 艺术家

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 _ arts 的第一行,但是这已经不起作用了。

我不能使用 TOP,因为我的数据库,我不能按 feeds_artists.artist_id分组的结果,因为我需要按日期排序(我得到的结果分组他们这种方式,但结果不是最新的)

尝试了一些与外部应用程序以及-没有成功以及。 老实说,我真的无法想象在这些行发生了什么-可能是最大的原因,为什么我不能得到这个工作。

解决方案:

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'
304034 次浏览

如果可以假定艺术家 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

没有选择的版本:

   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

我用过一些别的东西(我觉得更好... ...) ,并想与大家分享:

我创建了一个包含“ group”子句的 VIEW

CREATE VIEW vCountries AS SELECT * PROVINCES GROUP BY country_code


SELECT * FROM client INNER JOIN vCountries on client_province = province_id

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

希望能有所帮助!

我想给一个更多的 一般答案。一个将处理 任何情况下,如果只想选择左连接中的第一个项目

您可以使用 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作为我们的 订购人选项,这将返回一个类似“ Zack”的 Person id。如果我们想要一个像“安迪”这样的名字,我们会把 订单来自名字 DESC改成 订单来自名字 ASC

这是灵活的,因为这地方的力量订购完全在你的手中。但是,经过大量的测试,它不会扩大规模处于用户众多、数据量大的情况下。

但是,它在为管理员运行数据密集型报告时非常有用。

@ 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'

基于这里的几个答案,我发现了一些对我有用的东西,我想概括并解释一下到底发生了什么。

转换:

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要比较联接表的主键。

您可以使用内部查询(即订单 + 限制) ,但它必须返回所需行的一个主键,这个主键将告诉 ON要连接的确切行。

更新-用于 MySQL 5.7 +

与 MySQL 5.7 + 相关的另一个选项是使用 ANY_VALUE + GROUP BY。它将选择一个不一定是第一个艺术家的名字。

SELECT feeds.*,ANY_VALUE(feeds_artists.name) artist_name
FROM feeds
LEFT JOIN feeds_artists ON feeds.id = feeds_artists.feed_id
GROUP BY feeds.id

更多关于 ANY _ VALUE: https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html的信息

下面是我用分组从句给出的答案。

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

对于 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

我知道这不是一个直接的解决方案,但是因为我遇到了这个问题,这对我来说一直是个大问题,而且使用 left join select 等有时会导致数据库和服务器的大量处理成本,我更喜欢在 php 中使用 array 来做这种 left join:

首先从第二个表获取范围内的数据,当您只需要从第二个表获取一行数据时,只需将它们与左连接共用列保存为结果数组中的键。

问题1:

$sql = SELECT artist_id FROM feeds_artists fa WHERE fa.feed_id {...RANGE...}
$res = $mysqli->query($sql);
if ($res->num_rows > 0) {
while ($row = $res->fetch_assoc()) {
$join_data[...$KEY...] = $row['artist_id'];
}

然后,从前面的数组中获取基本数据并添加左连接表的细节,像下面这样获取它们:

问题2:

$sql = SELECT * FROM feeds f WHERE f.id {...RANGE...};
$res = $mysqli->query($sql);
if ($res->num_rows > 0) {
while ($row = $res->fetch_assoc()) {
$key = $row[in_common_col_value];
$row['EXTRA_DATA'] = $join_data[$key];
$final_data[] = $row;
}

现在,您将拥有一个 $final _ data 数组,它希望从 $join _ data 数组中获得额外的数据。这通常适用于日期范围数据,如下所示。