我遇到了一个场景,我需要在从“遗留”到当前的交叉点返回一组复杂的计算值。
长话短说,我有这样的事情......
with someofit as
(
select id, col1, col2, col3 from table1
)
select someofit.*,
case when id < @lastLegacyId then
(select ... from table2 where something = id) as 'bla'
,(select ... from table2 where something = id) as 'foo'
,(select ... from table2 where something = id) as 'bar'
else
(select ... from table3 where something = id) as 'bla'
,(select ... from table3 where something = id) as 'foo'
,(select ... from table3 where something = id) as 'bar'
end
from someofit
不,这就是问题所在......我不想不断地对每个子选择进行案例检查,但同时当该条件适用时,我需要相关案例块中的所有选择。
有没有更聪明的方法来做到这一点?
如果我使用正确的面向对象语言,我会使用这样的东西......
var common = GetCommonSuff()
foreach (object item in common)
{
if(item.id <= lastLegacyId)
{
AppendLegacyValuesTo(item);
}
else
{
AppendCurrentValuesTo(item);
}
}
我最初确实尝试使用联合进行 2 个完整的选择,但由于效率/要评估的行数,这不能很好地工作。
子选择正在寻找满足某些条件的总行数,而不是表 2 或 3 上的 id 匹配,但这些表中可能有数百万行。
使用 cte 有两个原因...
首先,它只从表 1 中提取我感兴趣的行,因此我只在每种情况下只做一小部分子选择。
其次,它在表 1 上的一次查找中返回常见的东西
有任何想法吗?
编辑 1:
这种情况的一些背景......
我有一个名为“imports”的表(上面的表 1),它代表一个导入作业,我们从文件(csv 或类似文件)中获取数据并将记录拉入数据库。
然后我有一个名为“步骤”的表,它代表我们经历的处理/清理规则,每条记录都包含一个存储过程名称和一堆关于规则的其他内容。
然后有一个连接表,表示特定导入“ImportSteps”的规则(上面的表 2 - 用于当前数据),其中包含“rowsaffected”列和导入 ID
所以对于当前的工作,我的 sql 非常简单......
从导入中选择 123 456 加入导入步骤
对于较旧的遗留东西,但是我必须查看表 3 ...表 3 是保存表,它包含曾经导入的每条记录,每一行都有一个导入 ID,每一行都包含键值。
在表 2 上影响到导入 id x 的新数据行上,其中步骤 id 为 y 将返回我的值。
在遗留数据上,我必须计算其中 col z = something 的行数
我需要大约 20 个导入的数据,并且这些数据绑定到我的 mvc Web 应用程序上的“datagrid”(如果这有什么不同的话)
我使用的 cte 通过一些参数确定“当前 20 个我感兴趣”这些参数代表开始和结束记录(按导入 ID 排序)。
我最大的问题是持有表......它是巨大的......众所周知,个别工作本身包含 500k + 条记录,并且该表包含多年的导入行,所以我需要我在该表上的查找尽可能快并且尽可能少。
编辑2:
实际解决方案(仅 suedo 代码)...
-- declare and populate the subset to reduce reads on the big holding table
declare table @holding ( ... )
insert into @holding
select .. from holding
select
... common stuff from inner select in "from" below
... bunch of ...
case when id < @legacy then (select getNewValue(id, stepid))
else (select x from @holding where id = ID and ... ) end as 'bla'
from
(
select ROW_NUMBER() over (order by importid desc) as 'RowNum'
, ...
) as I
-- this bit handles the paging
where RowNum >= @StartIndex
and RowNum < @EndIndex
我仍然有信心我可以清理更多,但我原来的查询看起来像票据解决方案的执行时间大约是 45 秒,这大约是 7