【问题标题】:Refactoring SQL query重构 SQL 查询
【发布时间】:2018-09-14 23:23:05
【问题描述】:

我有以下 SQL 查询,我想重构它。我对 SQL 很陌生,但我学到了一些我不应该在查询中重复做的事情。

SELECT id,
(​SELECT​ ​COUNT​(*)​ ​FROM​ Table_1 ​
WHERE​ T3.​Id ​=​ randomID)​ ​AS​ ​'Column One Count'​,

(​SELECT​ ​COUNT​(*)​ ​FROM​ Table_2 ​
WHERE​ T3.​Id ​=​ randomID)​ ​AS​ ​'Column Two Count'​,

((​SELECT​ ​COUNT​(*)​ ​FROM​ Table_2 
​WHERE​ T3.​Id ​=​ randomID)​ ​/​

(​SELECT COUNT​(*)​ ​FROM​ Table_1 ​
WHERE​ T3.​Id ​=​ randomID))​ ​*​ 100 ​AS​ 'Column Three Percentage' 
FROM Table_3 T3

有人建议我不要经常使用 SELECT *,所以我将每次出现的地方都替换为:

SELECT COUNT(randomID)

这给了我同样的结果。我仍然认为我可以将重复的元素组合成一个更简洁的查询,但是我的 SQL 水平还不够好。

有哪些方法可以重构此代码以避免重复类似查询?

【问题讨论】:

  • table1 和 table2 中还有列吗?
  • 或者您能提供一些示例数据并期待结果吗?

标签: sql sql-server azure


【解决方案1】:

一个简单的方法使用apply

select t3.id, t1.col1_cnt, t2.col2_cnt,
       t2.col2_cnt * 100.0 / t1.col1_cnt as col3_percentage
from Table_3 t3 outer apply
     (select count(*) as col1_cnt
      from table_1 t1
      where t3.id = t1.randomid
     ) t1 outer apply
     (select count(*) as col2_cnt
      from table_2 t2
      where t3.id = t2.randomid
     ) t2;

apply 本质上允许您将相关子查询移动到from 子句。一旦它们在那里,您就可以多次参考它们生成的列。

编辑:

如果您担心被零除,请使用nullif()

select t3.id, t1.col1_cnt, t2.col2_cnt,
       t2.col2_cnt * 100.0 / nullif(t1.col1_cnt, 0) as col3_percentage

【讨论】:

  • 小心除以0,你应该使用case ;)
  • @Esperento57 。 . . nullif() 优于 case(更短)。
  • 它的方法和其他方法一样 :)
【解决方案2】:

对于计数,您也许可以将这些表合并在一起;像这样:

select Ct = count(1)
from table_1
where Id = @RandomId
union 
select count(1)
from table_2
where Id = @RandomId'

我没有充实所有的专栏,但希望总体思路是有意义的。

select * 的内容而言,一般来说,出于多种原因,您可以避免使用它(包括它只是比您可能需要的更多的数据、容易受到架构更改的影响,并且几乎会生成非聚集索引在膝盖骨)。在旧版本的 SQL 中,它扩展到 count(*) 之类的东西。但是,只要您使用 SQL 2008+,count()(以及一些其他子句,如 EXISTS)就足够聪明,不会实际选择任何列。所以假设你只想计算每一行(甚至是空值),所有这些都是等价的

select 
    count(1),
    count(*),  
    count(primarykeycolumn) -- guaranteed not to be null
from myTable

【讨论】:

    【解决方案3】:

    我的提议:

    With CountT1 as (
    select f1.randomID, count(*) NbT1
    from Table_1 f1 inner join Table_3 f3 on f3.Id=f1.randomID
    group by f1.randomID
    ),
    CountT2 as (
    select f1.randomID, count(*) NbT2
    from Table_2 f1 inner join Table_3 f3 on f3.Id=f1.randomID
    group by f1.randomID
    )
    select T3.Id, 
    isnull(T1.NbT1, 0) as ​'Column One Count', 
    isnull(T2.NbT2, 0) as ​'Column Two Count', 
    case when T1.NbT1=0 then null else (T2.NbT2 /  T1.NbT1) * 100.0 end  as 'Column Three Percentage'
    from Table_3 T3
    left outer join CountT1 T1 on T3.Id=T1.randomID
    left outer join CountT2 T2 on T3.Id=T2.randomID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多