我有两张桌子
(1) MonthlyTarget {SalesManCode, TargetMonthYear, TargetValue};
此表有1966177行。
(2) MonthlySales {SalesManCode, SaleDate, AchievedValue};
此表有400310行。
我必须创建一个产生类似下表的结果的查询:
{SalesManCode, JanTar, JanAch, FebTar, FebAch,....., DecTar, DecAch}
问题是,加入这两个表需要很长时间。
查询应该是什么?
如何优化查询?
我不想考虑索引。
答案 0 :(得分:4)
好吧,如果您不想考虑索引,那么您将始终执行全表扫描并且性能不会得到改善。
答案 1 :(得分:3)
检查表格的正确索引。如果不查看数据库本身几乎是不可能的,但99%的时间缓慢连接是由于表索引不正确或丢失。
答案 2 :(得分:3)
看起来你在MonthlyTarget表中缺少一些列,即“TargetDate”列。
除了每个人已经说过的关于索引的内容之外,有时候分而治之的方法确实有帮助。不是将1966177行表连接到400310行表,而是创建小型临时表并将它们连接在一起:
CREATE TABLE #MonthlySalesAgg
(
SalesManCode int,
JanTar money,
FebTar money,
MarTar money,
AprTar money,
MayTar money,
JunTar money,
JulTar money,
AugTar money,
SepTar money,
OctTar money,
NovTar money,
DecTar money
PRIMARY KEY CLUSTERED (SalesManCode)
)
INSERT INTO #MonthlySalesAgg
SELECT *
FROM
(SELECT SalesManCode, TargetValue, SaleMonth = Month(TargetDate) FROM MonthlyTarget) as temp
PIVOT
(
Max(TargetValue)
FOR [SaleMonth] IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) as p
CREATE TABLE #MonthlyTargetAgg
(
SalesManCode int,
JanAch money,
FebAch money,
MarAch money,
AprAch money,
MayAch money,
JunAch money,
JulAch money,
AugAch money,
SepAch money,
OctAch money,
NovAch money,
DecAch money
PRIMARY KEY CLUSTERED (SalesManCode)
)
INSERT INTO #MonthlyTargetAgg
SELECT * FROM
(SELECT SalesManCode, AchievedValue, SaleMonth = Month(SaleDate) FROM MonthlySales) as temp
PIVOT
(
Sum(AchievedValue)
FOR [SaleMonth] IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) as p
上面的查询创建了两个中间表,这些中间表应包含与SalesMan表相同数量的记录。加入他们很简单:
SELECT *
FROM #MonthlyTargetAgg target
INNER JOIN #MonthlySalesAgg sales ON target.SalesManCode = sales.SalesManCode
如果您发现自己需要一直按月提取数据,请将代码移到视图中。
PIVOT需要SQL Server 2005或更高版本,而且它通常是一个非常有用的运算符。希望SQL Server 2008允许用户一次转动多个列,这将导致查询比上面显示的更简单。
使用SQL Server 2000:
PIVOT是语法糖。例如,
SELECT * FROM
(SELECT SalesManCode, AchievedValue, SaleMonth = Month(SaleDate) FROM MonthlySales) as temp
PIVOT
(
Sum(AchievedValue)
FOR [SaleMonth] IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) as p
变为
SELECT
SalesManCode,
[1] = Sum(case SaleMonth when 1 then AchievedValue else 0 end),
[2] = Sum(case SaleMonth when 2 then AchievedValue else 0 end),
[3] = Sum(case SaleMonth when 3 then AchievedValue else 0 end),
[4] = Sum(case SaleMonth when 4 then AchievedValue else 0 end),
[5] = Sum(case SaleMonth when 5 then AchievedValue else 0 end),
[6] = Sum(case SaleMonth when 6 then AchievedValue else 0 end),
[7] = Sum(case SaleMonth when 7 then AchievedValue else 0 end),
[8] = Sum(case SaleMonth when 8 then AchievedValue else 0 end),
[9] = Sum(case SaleMonth when 9 then AchievedValue else 0 end),
[10] = Sum(case SaleMonth when 10 then AchievedValue else 0 end),
[11] = Sum(case SaleMonth when 11 then AchievedValue else 0 end),
[12] = Sum(case SaleMonth when 12 then AchievedValue else 0 end)
FROM
(SELECT SalesManCode, AchievedValue, SaleMonth = Month(SaleDate) FROM MonthlySales) as temp
GROUP BY SalesManCode
答案 3 :(得分:1)
我不想考虑索引。
您必须考虑建立索引。无论你如何编写查询,db引擎别无选择,只能扫描每个表寻找连接,它可能会一遍又一遍地执行。你别无选择。
如果由于无法控制数据库而不想弄乱索引,请考虑将数据导出到本地SQL Express实例。
哎呀,即使将数据导出到平面文件,按SalesManCode对文件进行排序,编写一个简单的程序来读取和匹配它们也会更快。
答案 4 :(得分:1)
如果没有解雇一大批销售人员,请考虑以下选项:
答案 5 :(得分:0)
你有过滤器吗?您是否可以将部分结果存储在临时表中,然后在缩小数据大小后加入其余数据?
答案 6 :(得分:0)
如果索引不是一个选项,那么加速它的另一种方法是将它放在速度更快的服务器上。有些东西告诉我索引会更容易。