我正在处理此查询。当我从子查询到主查询分配日期过滤器时,响应时间从1秒增加到4.5分钟。
我不知道如何解决此问题并解决我的查询。我正在写查询和尝试过的方法。
谢谢您的帮助。
我的查询:
select
START_DATE as DATE,
[MINUTE] as MIN,
map1.LT,
ISNULL((SELECT
(SELECT CAST((main.MIN) AS FLOAT)) /
(
(nullif(
(select cast(
(select
sum(MIN2)
from fooTable2 d2
CROSS APPLY (select Top(1) LT from FooMap2 where x = d2.x) k2
where k2.LT = map1.LT
**-- PROBLEM CODE START**
and YEAR(d2.DATE) = YEAR(main.DATE) and MONTH(d2.DATE) = MONTH(main.DATE)
**-- PROBLEM CODE END**
) as float)),0))
as XX,
.......
......
from Table1 main
OUTER APPLY (select Top(1) LT from FooMap where x = main.x) map1
我尝试创建虚拟表。
但不起作用。
declare @child table ([Year] smallint, [Month] smallint, [Total] float,[LTCode] nvarchar(20))
insert into @child ([LTCode],[Year],[Month],[Total])
(select
k2.LT,YEAR(d2.DATE) as YIL,MONTH(d2.DATE) as AY,sum(MIN) as SURE
from DURUS d2
CROSS APPLY (select Top(1) LT from FooMap2 where x = d2.x) k2
group by k2.LT,YEAR(d2.DATE),MONTH(d2.DATE))
...
....
(select [Total] from @child where [YEAR] = YEAR(main.DATE) and [MONTH] = MONTH(main.DATE) and [LTCode] = map1.LT)
我该怎么办?
答案 0 :(得分:1)
根本问题是数据模型。您需要过滤月份和年份,但将数据存储为DATE,DATETIME或类似数据。 没有简单的方法可以快速实现这一目标:
super
WHERE FUNCTION(Input)= FUNCTION(Input)强制对每个表进行扫描,具有两个这样的过滤器意味着您要为每个表中的每一行两次触摸/评估每个值(d2.date和main.date)。要解决此问题,您最好的选择包括:
在每个表上按年份和月份添加一个持久化的计算列,然后添加适当的索引(按年,月,将查询中涉及的所有列添加为包含列。
使用索引视图来预先连接Durus和main,这并不简单,但是可行。
了解如何创建和利用索引正确的日历表。这将需要一些努力,但也会改变您的职业。
在联接的左侧使用其他过滤器...
例如:在and YEAR(d2.DATE) = YEAR(main.DATE)
and MONTH(d2.DATE) = MONTH(main.DATE)
之后添加WHERE子句,以过滤掉联接之前的所有其他行。
答案 1 :(得分:-1)
优化的常用方法: 1)从过滤器左侧删除计算 2)在单独的临时表或中间CTE查询中呈现子查询 3)不要使用表变量 4)在早期阶段,尝试在连接之前过滤尽可能多的数据