由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Database版 - 养老院人事 SQL难题解法综述 -- 申精
相关主题
webbew SQL问题解法1 -- 90%以上的数据库版SQL问题可以用partition by解决有没有TSQL和 PL/SQl 或者Teradata sql都熟悉的高手, 麻烦看一下
webbew SQL问题解法3 -- 还在远古时代总么办谁有临阵磨枪的有关SQL Server的题目?
来做sql题目。问个sql的问题吧,搞不出来了. (转载)
webbew SQL问题解法2 -- SQL 利器Recursive CTEquery analyzer VS. Stored procedure
sql面试题1怎么在openquey里传变量.
问一个query问一个数据处理的问题,该如何实现单列转多行?14楼有图更新 (转载)
问一个 SQL combine records问题请教:找出10天内下了超过5次单的customers
求助一个MS SQL的问题。 关于SSRS的How to delete 40 millions records in a 400 millions indexed table fast?
相关话题的讨论汇总
话题: 2012话题: ind1话题: t1话题: startdate话题: user
进入Database版参与讨论
1 (共1页)
t****n
发帖数: 10724
1
美女压阵
t****n
发帖数: 10724
2
*******************************************************************
HR SQL难题的三种解法
*******************************************************************
摘要
本文综合描术了针对养老院人事难题的多种SQL解法。
鸣谢
Beijing
===========================================================
解法1 -- Partition 法
===========================================================
可以参考wyr解法,本解法用了lead/lag,以及ROWS UNBOUNDED PRECEDING AND
CURRENT ROW
原理一样,就是要达到排序后分组的目的
借用原题数据,第一步的目标加上ind1,指示此行是否是超过30天的行
User StartDate EndDate ind1
1 12/2/2011 1/16/2012 0
1 3/4/2012 3/24/2012 1
1 4/5/2012 4/26/2012 0
1 5/14/2012 6/7/2012 0
2 3/5/2012 7/30/2012 0
2 8/4/2012 9/15/2012 0
3 6/5/2012 8/20/2012 0
假设结果是t1,t1是这样得到的,请自行优化
select t11.*,
(t11.startdate - (LEAD/LAG)? (end_date,1) over (PARTITION BY ?? ORDER BY ??
)) t11.ind11
from t t11
ind11是相差的天数,自行转化成ind1 0(<=30),1(>30)
借用原题数据,第二步的目标加上ind2,指示分组
User StartDate EndDate ind1 ind2
1 12/2/2011 1/16/2012 0 0
1 3/4/2012 3/24/2012 1 1
1 4/5/2012 4/26/2012 0 1
1 5/14/2012 6/7/2012 0 1
2 3/5/2012 7/30/2012 0 0
2 8/4/2012 9/15/2012 0 0
3 6/5/2012 8/20/2012 0 1
假设结果是t2,t2是这样得到的,请自行优化
select t21.*,
(select sum(ind1) OVER (PARTITION BY id ORDER BY start_date ROWS UNBOUNDED .
... ) ind2
from t1 t21
分组成功,min,max
===========================================================
解法2 -- CTE 法
===========================================================
首先,这类复杂sql问题,建议大家用CTE(和Recursive无关),每一步都分开,思路会
清晰得多
with t1 as(
select ....
from ....),
t2 as (
select...
from t1, .....),
....
select
from tn
用过oracle connect by的同学,Recursive CTE实现了类似功能,而且是ansi的,推荐
大家使用,当然,本题用connect by也可以
对于解决本题,思路和用Analytic Functions类似,就是要达到排序后分组的目的,以
原题数据为例,如果有以下标记,用group by user,标记值可得到min(startdate),
max(enddate)即可
User StartDate EndDate 标记值
1 12/2/2011 1/16/2012 0
1 3/4/2012 3/24/2012 1
1 4/5/2012 4/26/2012 1
1 5/14/2012 6/7/2012 1
2 3/5/2012 7/30/2012 0
2 8/4/2012 9/15/2012 0
3 6/5/2012 8/20/2012 0
先看一下原理
http://www.nocoug.org/download/2010-05/2010_303_Fernandez_ppt.p
http://www.morganslibrary.org/reference/with.html
http://technet.microsoft.com/en-us/library/ms186243%28v=sql.105
问题就来了,我们的起始的SQL应该是什么呢?我们的recursive应该怎么连呢?很显然
我们的起始SQL应该是每个user最早的startdate记录,下面记录就应该是一个一个按
startdate的升序排列。我们原始table没有这个序列数据,所以我们要给它加上,结果
假设是t1(use CTE!!)
select *, row_number() over (partition by user order by startdate) rn
from table
有了t1,我们上面的2个问题都解决了。起始sql就是select *, rn from t1 where rn=
1,连接就是靠user=user and rn=rn+1。排序连接解决了,但是我们的分组问题还没有
解决,也就是我们的标记ind的值还没有解决。在我们的Recursive CTE加入ind,起始
sql里面ind的值假定是0(select *, rn, 0 ind from t1 where rn=1, 任何值都行)
。我们是否能使ind值达到上面例子里分组的目的呢。答案是肯定的,每一个record,
如果和前面比没超过30天,这个record的ind就沿用上一个record的ind;如果超过30天
,就在上一个的基础上+1。这样问题就解决了。
===========================================================
解法3 -- 古典 法
===========================================================
原理一样,就是要达到排序后分组的目的
借用原题数据,第一步的目标加上ind1,指示此行是否是超过30天的行
User StartDate EndDate ind1
1 12/2/2011 1/16/2012 0
1 3/4/2012 3/24/2012 1
1 4/5/2012 4/26/2012 0
1 5/14/2012 6/7/2012 0
2 3/5/2012 7/30/2012 0
2 8/4/2012 9/15/2012 0
3 6/5/2012 8/20/2012 0
假设结果是t1,t1是这样得到的,请自行优化
select t11.*,
t11.startdate - (select MAX(t12.enddate) from t t21 where .. < ..) ind11
from t t11
ind11是相差的天数,自行转化成ind1 0(<=30),1(>30)
借用原题数据,第二步的目标加上ind2,指示分组
User StartDate EndDate ind1 ind2
1 12/2/2011 1/16/2012 0 0
1 3/4/2012 3/24/2012 1 1
1 4/5/2012 4/26/2012 0 1
1 5/14/2012 6/7/2012 0 1
2 3/5/2012 7/30/2012 0 0
2 8/4/2012 9/15/2012 0 0
3 6/5/2012 8/20/2012 0 1
假设结果是t2,t2是这样得到的,请自行优化
select t21.*,
(select sum(ind1) from t1 t22 where ...<=....) ind2
from t1 t21
分组成功,min,max
B*****g
发帖数: 34098
3
你这是赤果果的剽窃,哈哈
t****n
发帖数: 10724
4
荣耀归北京
包子归北京

【在 B*****g 的大作中提到】
: 你这是赤果果的剽窃,哈哈
w*r
发帖数: 2421
5
MD,我就是打酱油的
B*****g
发帖数: 34098
6
一起打,玩sql的都是打酱油的

【在 w*r 的大作中提到】
: MD,我就是打酱油的
t****n
发帖数: 10724
7
credit to wyr

【在 w*r 的大作中提到】
: MD,我就是打酱油的
1 (共1页)
进入Database版参与讨论
相关主题
How to delete 40 millions records in a 400 millions indexed table fast?sql面试题1
请教一个问题问一个query
partition 表问一个 SQL combine records问题
今典问题: 这个Self Query咋写?求助一个MS SQL的问题。 关于SSRS的
webbew SQL问题解法1 -- 90%以上的数据库版SQL问题可以用partition by解决有没有TSQL和 PL/SQl 或者Teradata sql都熟悉的高手, 麻烦看一下
webbew SQL问题解法3 -- 还在远古时代总么办谁有临阵磨枪的有关SQL Server的题目?
来做sql题目。问个sql的问题吧,搞不出来了. (转载)
webbew SQL问题解法2 -- SQL 利器Recursive CTEquery analyzer VS. Stored procedure
相关话题的讨论汇总
话题: 2012话题: ind1话题: t1话题: startdate话题: user