简化同一公式

时间:2017-09-25 14:15:36

标签: tsql dataexplorer

是否可以简化多次写入相同公式的SEDE查询?

例如,this query正在写rtrim(LOWER(Title))五次:

select
    rtrim(LOWER(p.Title)),
    count(rtrim(LOWER(p.Title)))
from Posts p
group by rtrim(LOWER(p.Title))
having (count(rtrim(LOWER(p.Title))) > 1)
order by count(rtrim(LOWER(p.Title))) desc

在答案中,请说明您的因子分解是纯粹的装饰还是性能影响。

2 个答案:

答案 0 :(得分:1)

根据您的查询的link,为了进行比较,您似乎正在使用LOWER()RTRIM()函数。

默认情况下,

TSQL不区分大小写,右侧的尾随空格将被忽略。您可以通过以下方式获得相同的结果:

Select      Lower(P.Title), Count(P.Title)
From        Posts   P
Group By    Lower(P.Title)
Having      Count(P.Title) > 1
Order By    Count(P.Title) Desc

答案 1 :(得分:0)

首先 - 此处的永久解决方案是清理您的数据。使用LTRIM,RTRIM,UPPER,LOWER等功能可使 SARGEable。换句话说,您的查询可能会慢慢爬行,因为SQL Server无法在不扫描所有行的情况下从索引中检索所需的数据。

  

例如,这个查询写了五次rtrim(LOWER(Title)):

输入APPLY + VALUES内联别名技巧

这是我最初提出的用于简化代码的内容,但后来我发现了一些偶然的性能优势。首先是一些样本数据:

use tempdb;
go

create table dbo.sometable(someid int identity, somevalue decimal(10,2));
insert dbo.sometable(somevalue) values (100),(1050),(5006),(111),(4);

假设我们有一个查询,它接受一些变量或参数,对它们执行计算并在整个查询中使用该值。请注意下面的案例陈述。

declare @var1 int = 100, @var2 int = 50, @var3 int = 900;

select
  someid, 
    somevalue,
    someCalculation = 
      case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end,
  someRank = dense_rank() over (order by 
      case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end)
from dbo.sometable
where case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end
  between 900 and 2000
order by case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end;

我们可以像这样简化这个查询:

select 
  someid, 
  somevalue,
  someCalculation = i.v,
  someRank = dense_rank() over (order by i.v)
from dbo.sometable
cross apply (values
(
  case when @var3 < somevalue then (@var1/(@var2*2.00))+@var3 else @var3+somevalue end)
) i(v)
where i.v between 900 and 2000
order by i.v;

每个查询返回相同的结果。现在执行计划:

enter image description here

我们不仅简化了查询,还实际上加快了速度。在我的原始查询中,优化器必须两次计算相同的值并执行两种排序。使用我的内联别名技巧,我能够删除排序和计算