1

如果这在其他地方有答案,请提前道歉 - 我确实努力寻找但找不到。

我有一个名为“item”的表,有点像这样:

itemid applicationid value
   1        1        3.00
   2        2        1.00
   3        2        2.00
   4        3        4.00
   5        3        1.00

即一个应用程序可以有多个项目。还有更多的列,但没关系。我想根据申请总价值列出项目及其价值(以便我可以将项目价值计算为申请的比例)。

所以我有一个有点像这样的查询:

SELECT i.itemid, i2.applicationid, i.value, i2.totalvalue
FROM item i
JOIN (SELECT sum(value) AS totalvalue FROM item GROUP BY applicationid) i2
    ON i.applicationid = i2.applicationid
WHERE <some criteria that returns a hundred or so items>;

给我

itemid applicationid value totalvalue
   1        1        3.00     3.00
   2        2        1.00     3.00
   3        2        2.00     3.00
   4        3        4.00     5.00
   5        3        1.00     5.00

这可行,但是在项目表中有 100k 行时,它非常非常慢。我的探查器告诉我,问题在于有一个正在执行完整索引扫描的子查询。

我想知道使用 GROUP BY 的自联接是否会更快,但它不仅对第二个表进行分组,而且对所有内容进行分组。IE

SELECT i.itemid, i2.applicationid, i.value, sum(i2.value)
FROM item i
JOIN item i2 ON i2.applicationid = i.applicationid
WHERE <some criteria that returns a hundred or so items>
GROUP BY i2.applicationid;

每个 applicationid 我只得到 1 行,而不是每个 itemid 1 行。

有什么方法可以重写我的原始查询以使其更快?

非常感谢。

4

2 回答 2

1

您的查询没有子查询的连接条件,因此它在语法上不正确。您是否尝试过此查询:

SELECT i.itemid, i2.applicationid, i.value, i2.totalvalue
FROM item i JOIN
      (SELECT applicationid, sum(value) AS totalvalue
       FROM item
        GROUP BY applicationid
     ) i2
     on i.applicationid = i2.applicationid
WHERE <some criteria that returns a hundred or so items>; 

在某些数据库中,这可能作为相关子查询运行得更快,特别是如果您在 applicationid 上有索引:

SELECT i.itemid, i.applicationid, i.value,
       (select sum(value) from item i2 where i.applicationid = i2.applicationid
       ) as totalvalue
FROM item i JOIN
      (SELECT applicationid, sum(value) AS totalvalue
       FROM item
        GROUP BY applicationid
     ) i2
     on i.applicationid = i2.applicationid
WHERE <some criteria that returns a hundred or so items>; 

此外,这可能是您的 WHERE 标准再次减慢速度,具体取决于数据库。

于 2012-08-20T17:54:12.243 回答
-1

您可以尝试使用窗口函数来查看优化器是否很好地使用它们。我猜它会使用相同的执行计划,但值得一试。这是 SQL Server 的代码,它应该与 Oracle 类似。

SELECT i.itemid, i.applicationid, i.value, 
    sum(value) Over (Partition by i.applicationid) as totalvalue
FROM item i
WHERE <some criteria that returns a hundred or so items>;
于 2012-08-20T16:55:06.953 回答