我想联接两个表,但是在table1上每个记录仅获得1条table2记录
例如:
SELECT c.id, c.title, p.id AS product_id, p.title
FROM categories AS c
JOIN products AS p ON c.id = p.category_id
这将使我获得所有记录products
,这不是我想要的。我希望每个类别有1个[第一个]产品(我sort
在产品字段中有一个列)。
我该怎么做呢?
Answers:
我喜欢在类似问题中描述的另一种方法:https : //stackoverflow.com/a/11885521/2215679
特别是在需要在SELECT中显示多个字段的情况下,这种方法更好。为避免Error Code: 1241. Operand should contain 1 column(s)
或加倍为每个列选择子项。
对于您的情况,查询应如下所示:
SELECT
c.id,
c.title,
p.id AS product_id,
p.title AS product_title
FROM categories AS c
JOIN products AS p ON
p.id = ( --- the PRIMARY KEY
SELECT p1.id FROM products AS p1
WHERE c.id=p1.category_id
ORDER BY p1.id LIMIT 1
)
@ goggin13接受的答案似乎有误。迄今为止提供的其他解决方案都可以使用,但是会遇到n + 1问题,因此会降低性能。
n + 1个问题:如果有100个类别,那么我们将必须做1个选择来获得类别,然后对于返回的100个类别中的每一个,我们都需要进行选择以获取该类别中的产品。因此将执行101个SELECT查询。
我的替代解决方案解决了n + 1问题,因此,由于仅执行了2个选择,因此应具有更高的性能。
SELECT
*
FROM
(SELECT c.id, c.title, p.id AS product_id, p.title
FROM categories AS c
JOIN products AS p ON c.id = p.category_id
ORDER BY c.id ASC) AS a
GROUP BY id;
group_concat
确保结果按正确顺序排列。
ANY_VALUE()
按照dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
使用postgres时,可以使用DISTINCT ON
syntex来限制从任一表返回的列数。
这是代码示例:
SELECT c.id, c.title, p.id AS product_id, p.title
FROM categories AS c
JOIN (
SELECT DISTINCT ON(p1.id) id, p1.title, p1.category_id
FROM products p1
) p ON (c.id = p.category_id)
诀窍是不要直接在ID多次出现的表上联接,而是先创建一个表,每个ID仅出现一次
假设您希望列中的产品具有MIN()
不道德的价值sort
,它看起来应该像这样。
SELECT
c.id, c.title, p.id AS product_id, p.title
FROM
categories AS c
INNER JOIN (
SELECT
p.id, p.category_id, p.title
FROM
products AS p
CROSS JOIN (
SELECT p.category_id, MIN(sort) AS sort
FROM products
GROUP BY category_id
) AS sq USING (category_id)
) AS p ON c.id = p.category_id
带有3个嵌套表的另一个示例:1 / User 2 / UserRoleCompanie 3 / Companie
SELECT
u.id as userId,
u.firstName,
u.lastName,
u.email,
urc.id ,
urc.companieRole,
c.id as companieId,
c.name as companieName
FROM User as u
JOIN UserRoleCompanie as urc ON u.id = urc.userId
AND urc.id = (
SELECT urc2.id
FROM UserRoleCompanie urc2
JOIN Companie ON urc2.companieId = Companie.id
AND urc2.userId = u.id
AND Companie.isPersonal = false
order by Companie.createdAt DESC
limit 1
)
LEFT JOIN Companie as c ON urc.companieId = c.id
+---------------------------+-----------+--------------------+---------------------------+---------------------------+--------------+---------------------------+-------------------+
| userId | firstName | lastName | email | id | companieRole | companieId | companieName |
+---------------------------+-----------+--------------------+---------------------------+---------------------------+--------------+---------------------------+-------------------+
| cjjt9s9iw037f0748raxmnnde | henry | pierrot | henry@gmail.com | cjtuflye81dwt0748e4hnkiv0 | OWNER | cjtuflye71dws0748r7vtuqmg | leclerc |