【问题标题】:INNER JOIN SQL query includes duplicatesINNER JOIN SQL 查询包含重复项
【发布时间】:2021-03-04 21:04:39
【问题描述】:

我有一家在线商店,并试图在产品页面上展示五种类似的产品。我尝试使用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 是 ORDER BY 项目必须出现在选择列表中 指定。

有什么建议吗?

【问题讨论】:

    标签: sql sql-server subquery sql-order-by inner-join


    【解决方案1】:

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

    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;
    

    【讨论】:

      【解决方案2】:

      如果我没听错的话,你可以将逻辑移到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 个搜索标签的产品。

      【讨论】:

      • @gabenotgave:此查询将利用store_producttags(producid, tagid) 上的索引。您可能需要根据您的真实数据评估这两种解决方案,以找出性能最佳的解决方案。我很想知道!
      【解决方案3】:

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

      您希望每个产品 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)
                   );
      

      【讨论】:

      • 我实际上打算包括没有至少五个标签的产品。否则,这个解决方案肯定会奏效。谢谢! :)
      猜你喜欢
      • 2015-08-01
      • 1970-01-01
      • 2013-03-09
      • 2015-01-10
      • 1970-01-01
      • 2021-04-23
      • 2010-12-19
      • 2012-11-04
      • 2014-02-24
      相关资源
      最近更新 更多