1

我正在使用一个中等大小的 MSAccess .mdb 文件,我需要使用 SQL 来操作它。不幸的是,一些理论上有效的陈述似乎导致它挂起,我遇到了砖墙。

这是 SQL Fiddle 中的简化表示

三个表:products、product_category 和 categories 我需要选择仅包含具有“HIDE = 1”字段的项目的类别 如果类别包含隐藏 = 0 的产品,则不应选择它。

我可以使用子查询相对轻松地做到这一点,但查询会停止。在过去,依赖左连接的查询似乎可以有效地执行,但我无法将我的思想围绕在连接上,足以将此查询转换为那种格式。

编辑:

SELECT c.categoryid 
FROM product_category AS c
      LEFT JOIN
      (
          SELECT DISTINCT c.categoryid 
          FROM  product_category AS c
                LEFT JOIN products AS p 
                  ON c.catalogid = p.catalogid
          WHERE p.hide = 0
      )    y ON y.categoryid = c.categoryid

WHERE y.categoryid IS NULL

有人发布了上述查询作为答案,但由于某种原因将其删除。据我所知,它可以工作并且工作得很快。我认为这个问题可以回答。如果我记得,一旦计时器允许,我会自行发布答案。

4

2 回答 2

2

我相信您只需要取消关联子查询,例如...

SELECT c.categoryid FROM product_category AS c
WHERE c.categoryid NOT IN 

(SELECT DISTINCT c1.categoryid FROM product_category AS c1
LEFT JOIN products AS p ON c1.catalogid = p.catalogid
WHERE p.hide = 0)

请注意我如何将子查询product_category表别名c1c- 这意味着子查询将只执行一次,而不是对主查询的每一行执行一次。

SQL小提琴

请注意,毫无疑问,还有更多的效率有待发现,但我认为这足以满足您的目的。

事实上,这里不需要 LEFT JOIN 我不认为即...

SELECT c.categoryid FROM product_category AS c
WHERE c.categoryid NOT IN 

(SELECT DISTINCT c1.categoryid FROM product_category AS c1
INNER JOIN products AS p ON c1.catalogid = p.catalogid
WHERE p.hide = 0)

..这将为您提供一些额外的速度。

于 2012-10-23T15:02:02.800 回答
2

如果每个 catalogid 只有一个 categoryid,那么您可以去掉不同的:

Select
  c.id, c.categoryname
From
  category c
Where
  Not Exists (
    Select 
      'x'
    From 
      products p
        Inner Join
      product_category pc
        on pc.catalogid = p.catalogid
    Where
      pc.categoryid = c.id and
      p.hide = 0
  )

已编辑 - 小提琴中的测试数据似乎有误,我已更正。这应该现在可以工作

http://sqlfiddle.com/#!6/56f5e/1/0

于 2012-10-23T15:58:20.383 回答