INNER JOIN SQL查询包含重复项



我有一个在线商店,正试图在产品页面上显示五种类似的产品。产品和标签之间有一种多对多的关系,我正试图使用INNER JOIN来查询(联接表(。以下是我迄今为止的SQL查询:

SELECT TOP(5) *
FROM [Store_ProductTags] AS [s]
INNER JOIN [Store_Products] AS [s0] ON [s].[ProductId] = [s0].[Id]
ORDER BY CASE WHEN TagId IN (1, 17) THEN 0 ELSE 1 END;

它做了我想要的(即获得五个与正在显示的产品具有相同标签的产品(,然而,包括重复。。。

这是我得到的结果(注意ProductId为1的两条记录(:

ProductId   TagId       Name
10          17          Harlots - The Woman You Saw... (CD)
1           1           Unholy - Blood of the Medusa (CD)
44          1           Unholy - Blood of the Medusa (LP)
1           2           Unholy - Blood of the Medusa (CD)
2           2           Lye By Mistake - Arrangements for Fulminating Vective (CD)

我想排除重复项。到目前为止,我已经尝试了DISTINCTGROUP BY,正如不同问题中的其他回答所显示的那样,但都无济于事。当我在SELECT之后添加DISTINCT时,我收到的错误是…

如果select DISTINCT为指定。

有什么建议吗?

您可以按产品分组,并根据匹配标签的数量对结果进行排序:

SELECT TOP(5) p.Id, p.Name
FROM Store_Products AS p INNER JOIN Store_ProductTags AS s 
ON s.ProductId = p.Id
GROUP BY p.Id, p.Name
ORDER BY SUM(CASE WHEN s.TagId IN (1, 17) THEN 1 ELSE 0 END) DESC;

如果我正确理解,您可以将逻辑移动到order by子句中的子查询:

select top (5) p.*
from store_products p
order by 
case when exists (
select 1
from store_producttags pt
where pt.productid = p.id and pt.tagid in (1, 17) 
) 
then 0 
else 1 
end

这将选择5种产品,并将优先权授予拥有2个搜索标签的产品。

如果没有这样的标记,您的代码可以返回五个与任何标记都不匹配的产品。我不知道这是一个功能还是一个bug。根据查询的描述,这听起来像是一个bug。

你想要每个产品id一行。我猜你真的不需要匹配的标签。如果没有,最简单的方法是使用INEXISTS:过滤出不匹配的产品

SELECT TOP(5) sp.*
FROM Store_Products sp
WHERE EXISTS (SELECT 1
FROM Store_ProductTags spt
WHERE spt.[ProductId] = s.[Id] AND
spt.TagId IN (1, 17)
);

最新更新