【问题标题】:Rewrite a sql query for better optimization [closed]重写 sql 查询以获得更好的优化 [关闭]
【发布时间】:2025-11-30 12:30:02
【问题描述】:

我有一个包含以下数据的表

id orderid
1 0
1 1
1 2
2 0
3 0
3 1

一个 ID 可以有多个订单 ID。如果一个 id 只有一行 orderid 为 0 则表示该订单尚未下单。我已经找到了所有尚未下订单的 id。

这就是我的想法

Select *
From (
    Select
      id,
      orderId,
      Count(id) Over (partition by id) 'cntId'
    From table
) a
Where a.cntId = 1
and a.Orderid = 0

有没有更好的方法来编写这个查询?我将不胜感激。

【问题讨论】:

  • 桌子有PK吗?表有哪些索引?预期的结果是什么?

标签: sql sql-server database ssis msbi


【解决方案1】:

你可以这样试试

SELECT id
FROM yourTable
GROUP BY id
HAVING count(*)=1
       and max(orderid)=0;

【讨论】:

  • 由于COUNT(*),此答案可能无法使用任何索引
  • @TimBiegeleisen 在(id, orderid) 上的索引将导致Stream Aggregate 没有Sort,非常有效
【解决方案2】:

如果你想采用聚合方式,我更喜欢:

SELECT id
FROM yourTable
GROUP BY id
HAVING MIN(orderid) = MAX(orderid) AND MIN(orderid) = 0;

此查询应该受益于(id, groupid) 上的索引。

我的回答没有选择 groupid 值,但我们已经知道对于整个结果集,该值必须为零。

【讨论】:

    【解决方案3】:

    如果您知道 / 订单 ID 的顺序将始终为 0、1、2 等,并且您在 (id, orderid) 上有一个索引,我会自行加入,因此它不需要查询对于那些可能有 100 多个订单的 ID

    select
          yt.id
       from
          YourTable yt
             LEFT JOIN YourTable yt2
                on yt.id = yt2.id
               and yt2.orderid = 1
       where
              yt.orderid = 0
          AND yt2.id is null
    

    所以它只会关心订单 ID = 0 或 1,并且只返回那些没有找到 orderID = 1 的订单。

    【讨论】:

    • NOT EXISTS 可能会更好