Sql,少一些join吧

一、这是我自己写的第一段脚本,只考虑了结果,性能完全没考虑

-- 六月份
select 
A.empNo,
A.empName,
convert(decimal(6,3),A.conNum/(A.conNum+B.notConNum+0.0)) as connRate,
'2016-06' as yearMonth
from
(
select empNo,empName,count(0) as conNum
from bill with(nolock)
where beginTime >= '2016-06-01'
and beginTime < '2016-7-01'
and duration > 0
group by empNo,empName
) A
left join 
(
 select empNo,empName,count(0) as notConNum
 from bill with(nolock)
 where beginTime >= '2016-06-01'
 and beginTime < '2016-07-01'
 and duration = 0
 group by empNo,empName
) B on A.empNo = B.empNo
order by A.empNo;

-- 七月份
select 
A.empNo,
A.empName,
convert(decimal(6,3),A.conNum/(A.conNum+B.notConNum+0.0)) as connRate,
'2016-07' as yearMonth
from
(
select empNo,empName,count(0) as conNum
from bill with(nolock)
where beginTime >= '2016-07-01'
and beginTime < '2016-08-01'
and duration > 0
group by empNo,empName
) A
left join 
(
 select empNo,empName,count(0) as notConNum
 from bill with(nolock)
 where beginTime >= '2016-07-01'
 and beginTime < '2016-08-01'
 and duration = 0
 group by empNo,empName
) B on A.empNo = B.empNo
order by A.empNo;
二、这是我优化后的sql,没有减少join,但是从验证结果看性能有明显提升,
看来临时表某些场景下可以作为替换子查询以提高查询性能的一种方式:
-- 六月份
select empNo,empName,count(0) as conNum
into #TMP1
from bill with(nolock)
where beginTime >= '2016-06-01'
and beginTime < '2016-07-01'
and connection = 1
group by empNo,empName;

select empNo,empName,count(0) as notConNum
into #TMP2
from bill with(nolock)
where beginTime >= '2016-06-01'
and beginTime < '2016-07-01'
and connection = 0
group by empNo,empName;

select 
A.empNo,
A.empName,
convert(decimal(6,3),A.conNum/(A.conNum+B.notConNum+0.0)) as connRate,
'2016-06' as yearMonth
from #TMP1 A
left join #TMP2 B on A.empNo = B.empNO
order by A.empNo;

drop table #TMP1;
drop table #TMP2;

-- 七月份略
三、这是DBA优化后的脚本,看过脚本后,整个人不好了,DBA之前
分享过类似的优化技巧,居然没有想到用。这段脚本无论是从简洁性
还是减少io读写上都优化了很多。为了让自己长点记性,整理出来。
select yearMonth
,empNo
,empName
,convert(decimal(6,3),1.0 * conNum/(conNum + notConNum)) as connRate
from (
 select convert(char(7),beginTime,120) AS yearMonth
 ,empNo
 ,empName
 ,sum(case when duration > 0 then 1 else 0 end) conNum
 ,sum(case when duration = 0 then 1 else 0 end) notConNum
 from bill with(nolock)
 where beginTime >= '2016-06-01'
 and beginTime < '2016-08-01'
 group by convert(char(7),beginTime,120),empNo,empName
) t



### SQL 中 `CROSS JOIN` 的使用方法 在 SQL 查询中,`CROSS JOIN` 是一种用于生成两个或多个表之间笛卡尔积的操作符。这意味着第一个表中的每一行都会与第二个表中的每一行配对,形成一个新的结果集[^5]。 #### 基本语法结构 SQL 中 `CROSS JOIN` 的基本语法规则如下所示: ```sql SELECT ColumnName_1, ColumnName_2, ..., ColumnName_N FROM Table_1 CROSS JOIN Table_2; ``` 此查询会返回由 `Table_1` 和 `Table_2` 组成的结果集中所有的列,并且每一对来自不同表格的数据行都将被组合在一起[^3]。 #### 实际应用案例 为了更好地理解如何运用 `CROSS JOIN` ,可以考虑这样一个场景:假设有一个包含月份列表的表 (`Months`) 以及另一个存储销售区域信息的表 (`Regions`) 。如果希望创建一份报告来展示每个月份和地区之间的所有可能组合情况,则可以通过执行下面这段代码实现目标[^4]: ```sql SELECT m.Month_Name AS Month, r.Region_Name AS Region FROM Months m CROSS JOIN Regions r; ``` 上述命令将会输出一个新表,在其中包含了每一个月对应于各个地区的信息条目;即使某个月份内并没有实际发生任何交易活动也依然会被列出并用零或其他默认值填补空白处。 #### 结合其他函数处理缺失数据 当利用 `CROSS JOIN` 创建全面性的报表时,可能会遇到某些特定条件下缺乏相应记录的情形。此时可借助像 `COALESCE()` 这样的内置功能来设定缺省数值作为替代选项,从而确保最终呈现出来的统计资料更加完善和直观。 例如,对于那些不存在具体销售额度的情况,可以在查询语句里加入 `COALESCE(Sales_Amount, 0)` 来保证即便没有任何收入也会显示为 "0" 而不是 NULL 或者留白状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值