这个场景基于 another question 中的模式,我对任何关于模式有效性的讨论都不感兴趣!
我很想知道 SQL Server 中是否有任何好的技术可以根据另一列( amount1
)的不同值来执行一列(下面的 id1
)的聚合。
下面的 Plan1 扫描 table1 两次,通过 p_id 执行两次聚合,然后将结果连接在一起。这似乎可以改进。在某些情况下,查询 2 可能会返回错误的结果,而且计划更糟!
有任何想法吗?
数据线
IF OBJECT_ID('tempdb..#table1') IS NOT NULL DROP TABLE #table1;
IF OBJECT_ID('tempdb..#table2') IS NOT NULL DROP TABLE #table2;
CREATE TABLE #table1 (id1 int primary key nonclustered, amount1 int, p_id int);
CREATE CLUSTERED INDEX ix ON #table1 (p_id,id1);
INSERT INTO #table1
SELECT 1,500,10 UNION ALL
SELECT 2,700,20 UNION ALL
SELECT 3,500,10 UNION ALL
SELECT 4,450,20 UNION ALL
SELECT 5,300,10;
CREATE TABLE #table2 (id2 int primary key, amount2 int, id1 int);
INSERT INTO #table2
SELECT 1,300,1 UNION ALL
SELECT 2,200,1 UNION ALL
SELECT 3,200,2 UNION ALL
SELECT 4,500,2 UNION ALL
SELECT 5,400,3 UNION ALL
SELECT 6,150,4 UNION ALL
SELECT 7,300,4 UNION ALL
SELECT 8,300,5;
查询 1
WITH t1
AS (SELECT p_id,SUM(amount1) AS total1
FROM #table1
GROUP BY p_id),
t2
AS (SELECT p_id,SUM(amount2) AS total2
FROM #table2 table2
JOIN #table1 table1
ON table1.id1 = table2.id1
GROUP BY p_id)
SELECT t1.p_id,total1,total2
FROM t1
JOIN t2
ON t1.p_id = t2.p_id
方案一
查询 2
SELECT table1.p_id,
FLOOR(SUM(DISTINCT amount1 + table1.id1/100000000.0)) AS total1,
SUM(amount2) AS total2
FROM #table1 table1 JOIN #table2 table2 ON table1.id1=table2.id1
GROUP BY table1.p_id
方案二
最佳答案
好吧,@Quassnoi 解决方案看起来不错。无论如何,对于 SQL Server 2005+,您可以使用 PARTITION BY
子句尝试进行更简单的查询,但执行计划并不是更好,尽管这并不一定意味着效率更高或更低。
SELECT A.p_id, MIN(amount1) total1, SUM(amount2) total2
FROM (SELECT p_id, id1, SUM(amount1) OVER(PARTITION BY p_id) amount1 FROM #table1) A
JOIN #table2 B
ON A.id1 = B.id1
GROUP BY A.p_id
关于sql - 根据另一列的不同值聚合一列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4564348/