只有第一行的左外连接

Posted

技术标签:

【中文标题】只有第一行的左外连接【英文标题】:Left outer join with only first row 【发布时间】:2016-11-04 13:36:17 【问题描述】:

我有一个类似的查询

SELECT S.product_id, S.link, C.id AS category_id
FROM Products P
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1
LEFT OUTER JOIN Categories C ON c.product_id = P.id
WHERE P.active = 1

只要每个产品只分配到一个类别,我就可以正常工作。但是,如果一个产品被分配到多个类别,它会返回所有可能的组合。

我可以只选择第一个吗,如果产品没有任何类别,则链接仍应返回 category_id = NULL

【问题讨论】:

The first one,根据什么标准? 您可以在 category_id 上添加 MIN 或 MAX 和 GROUP BY。如果这还不够好,请将类别移动到子查询中。 【参考方案1】:

一个简单的方法是使用外部应用,以便有一个相关的连接,并使其成为前 1 个查询。因此,您可以访问相关类别记录的所有列。我在这里添加一个类别名称作为示例:

select s.product_id, s.link, c.id as category_id, c.name as category_name
from products p
inner join seo s on s.product_id = p.id 
outer apply
(
  select top 1 * 
  from categories cat
  where cat.product_id = p.id
  order by cat.id
) c
where p.active = 1
and p.product_type = 1;

【讨论】:

通过使用外部应用,也可以按类别表上的任何列进行排序,这可能是他需要的。【参考方案2】:

您可以使用GROUP BY 和Aggregate 函数来完成此操作,很可能是MIN 或MAX。

根据您在结果中喜欢的类别 ID,您可以选择最小值。

SELECT S.product_id, S.link, MIN(C.id) AS category_id
FROM Products P
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1
LEFT OUTER JOIN Categories C ON c.product_id = P.id
WHERE P.active = 1
GROUP BY S.product_id, S.link

或最大值。

SELECT S.product_id, S.link, MAX(C.id) AS category_id
FROM Products P
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1
LEFT OUTER JOIN Categories C ON c.product_id = P.id
WHERE P.active = 1
GROUP BY S.product_id, S.link

【讨论】:

这不会返回多行吗? MAX/MIN函数应用于结果集,它不会过滤结果集中的行... @JustinRowe GROUP BYproduct_idlink 的组合限制为一行。【参考方案3】:

使用子查询的替代解决方案:

SELECT S.product_id, S.link, 
(
 SELECT C.id FROM Categories C WHERE C.product_id = P.id AND
 ROW_NUMBER() OVER(ORDER BY /* your sort option goes here*/ ) = 1
) AS category_id
FROM Products P
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1
WHERE P.active = 1

【讨论】:

以上是关于只有第一行的左外连接的主要内容,如果未能解决你的问题,请参考以下文章

使用 LINQ 查询语法 EF Core C# 的左外连接

真正的左外连接

Spark 使用左外连接给出不正确的结果

如何在雪花的左外连接期间提取所有值(即使是那些不匹配的值)?

linq中的左外连接

LINQ:具有多个条件的左外连接