【问题标题】:MSSQL Select with "vertical"-whereMSSQL Select with "vertical"-where
【发布时间】:2012-02-14 12:37:32
【问题描述】:

我真的不知道如何解释,除了“垂直位置”。

想象一下下表:

TAGID|PRODUCTID|SHOP_ID
59   |3418-7   |38
61   |3418-7   |38
60   |4227-4   |38
61   |4227-4   |38

现在我想返回所有与标签 ID 相关的产品 ID:59,61。换言之,两个标签 ID 都存在行的产品 ID 值。

所以我想返回 3418-7,而不是 4227-4

如何在 SQL 语句中写得尽可能简单?

这是我目前的工作声明,但我觉得这可以以更聪明的方式完成:

SELECT 
  productid 
FROM shop_tag_relations 
WHERE 
  productid IN (select productid from shop_tag_relations WHERE tagid=59) 
AND 
  productid IN (select productid from shop_tag_relations WHERE tagid=61)
GROUP BY productid,shop_id

【问题讨论】:

  • 这是什么意思? “所有与 tagid 相关的产品 ID:59,61”
  • 返回与 tagid 59 和 61 相关的 productid。这是一个关系表,它绘制一个表中的产品和另一个表中的标签之间的关系。例如,如果 3418 是男士棕色鞋,标签 59 可能是鞋子,标签 61 可能是男士,72 棕色等等。

标签: sql-server select relational-division


【解决方案1】:
SELECT PRODUCTID
FROM T
WHERE TAGID IN (59,61)
GROUP BY PRODUCTID
HAVING COUNT(DISTINCT TAGID) = 2

或者

SELECT PRODUCTID
FROM T
WHERE TAGID = 59
INTERSECT
SELECT PRODUCTID
FROM T
WHERE TAGID = 61

【讨论】:

  • @EugenRieck - 使用正确的索引JOININTERSECT 应该与GROUP BY 一样快或更快。它们只是不太方便扩展。
  • INTERSECT 的可移植性比 GROUP BY 差得多,JOIN 比 GROUP BY 复杂得多,标签更多 - 所以归根结底,我认为 GROUP BY 是最佳解决方案
【解决方案2】:
SELECT DISTINCT 
a.PRODUCTID 
FROM mytable AS a
INNER JOIN mytable AS b ON a.PRODUCTID=b.PRODUCTID
WHERE a.TAGID=59
AND b.TAGID=61
;

【讨论】:

  • 此问题的每个解决方案都存在缩放问题(您的初始解决方案,我的回答)或不可移植(相交)。选择你的毒药。关键是,查询计划器将高度优化 JOIN 解决方案,TAGID 上是否有索引。
【解决方案3】:
SELECT ProductId
FROM shop_tag_relations 
WHERE TAGID IN (59,61)
GROUP BY ProductId
HAVING COUNT(DISTINCT TagId) = 2

【讨论】:

    猜你喜欢
    • 2019-05-12
    • 1970-01-01
    • 2011-11-28
    • 2013-04-08
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2013-04-10
    相关资源
    最近更新 更多