将SQL子查询转换为更高效的版本

时间:2012-10-23 14:57:20

标签: sql ms-access-2007

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

Here is a simplified representation in SQL Fiddle

三个表:products,product_category和categories 我需要SELECT类别只包含字段'HIDE = 1'的项目 如果某个类别包含hide = 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

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

2 个答案:

答案 0 :(得分: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表别名为c1而不是c - 这意味着子查询只执行一次,而不是主查询的每一行执行一次

SQL Fiddle

请注意,毫无疑问更多的效率仍然存在,但我认为这足以达到您的目的。

事实上,这里不需要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)

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

答案 1 :(得分: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