在Row_Number函数

时间:2017-04-19 11:49:05

标签: sql sql-server window-functions

我正在尝试使用以下查询来搜索记录:

SELECT 
ROW_NUMBER() over (partition by 
TW.EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate 
order by TW.EMPL_ID,TW.Effective_Bdate) RN,
TW.EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate,Effective_BDate from 
TT_EMPLOYEE_WORKDAY TW
where TW.HR_DOMAIN_CODE = 'SGP'

但是,生成的Row_Number计算列仅显示第一列的分区。理想情况下,我希望Row_Number具有相同的值,其中按列数据的分区是相同的。

我可能出错的任何线索?

使用RANK或DENSE RANK不是一个选项,因为我想识别多个员工的所有此类行,其中EMPL_ID,HR_DEPT_ID和Transfer_StartDate相同(RN = 1)

Sample data:
RN  AON_EMPL_ID   HR_DEPT_ID    Transfer_Startdate  Effective_BDate
1   0100690       69895             01/01/2017       2017-01-01
2   0100690       69895             01/01/2017       2017-01-03
3   0100690       69895             01/01/2017       2017-01-04

3 个答案:

答案 0 :(得分:0)

SELECT 
RANK() over (partition by   --or DENSE_RANK()
TW.EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate 
order by TW.EMPL_ID,TW.Effective_Bdate) RN,
TW.EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate,Effective_BDate from 
TT_EMPLOYEE_WORKDAY TW
where TW.HR_DOMAIN_CODE = 'SGP'

<强>更新

SELECT 
RANK() over (partition by   --or DENSE_RANK()
TW.EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate 
order by TW.EMPL_ID) RN,
TW.EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate,Effective_BDate from 
TT_EMPLOYEE_WORKDAY TW
where TW.HR_DOMAIN_CODE = 'SGP'
Order by RN,TW.Effective_Bdate

答案 1 :(得分:0)

将样本数据扩展为:

create table t (
    aon_empl_id varchar(16)
  , hr_dept_id varchar(16)
  , Transfer_Startdate date
  , Effective_bdate date
);
insert into t values 
 ('0100690','69895','01/01/2017','2017-01-01')
,('0100690','69895','01/01/2017','2017-01-03')
,('0100690','69895','01/01/2017','2017-01-04')
,('0200700','69895','01/01/2016','2016-01-01')
,('0200700','69895','01/01/2016','2016-01-03')
,('0200700','69896','01/01/2017','2017-01-04')
,('0200700','69896','01/01/2017','2017-01-04');

使用top with ties

select top 1 with ties
    aon_empl_id
  , hr_dept_id
  , Transfer_Startdate = convert(char(10),Transfer_Startdate,120)
  , Effective_bdate    = convert(char(10),Effective_bdate,120)
from t
order by row_number() over (
      partition by aon_empl_id, hr_dept_id, Transfer_Startdate 
      order by Effective_bdate
      )

rextester演示:http://rextester.com/KOIZ42069

返回:

+-------------+------------+--------------------+-----------------+
| aon_empl_id | hr_dept_id | Transfer_Startdate | Effective_bdate |
+-------------+------------+--------------------+-----------------+
|     0100690 |      69895 | 2017-01-01         | 2017-01-01      |
|     0200700 |      69895 | 2016-01-01         | 2016-01-01      |
|     0200700 |      69896 | 2017-01-01         | 2017-01-04      |
+-------------+------------+--------------------+-----------------+

使用common table expression row_number()的替代方案:

;with cte as (
select
    rn = row_number() over (
      partition by aon_empl_id, hr_dept_id, Transfer_Startdate 
      order by Effective_bdate
    )
  , aon_empl_id
  , hr_dept_id
  , Transfer_Startdate = convert(char(10),Transfer_Startdate,120)
  , Effective_bdate    = convert(char(10),Effective_bdate,120)
from t tw
)

select *
from cte
where rn = 1

返回:

+----+-------------+------------+--------------------+-----------------+
| rn | aon_empl_id | hr_dept_id | Transfer_Startdate | Effective_bdate |
+----+-------------+------------+--------------------+-----------------+
|  1 |     0100690 |      69895 | 2017-01-01         | 2017-01-01      |
|  1 |     0200700 |      69895 | 2016-01-01         | 2016-01-01      |
|  1 |     0200700 |      69896 | 2017-01-01         | 2017-01-04      |
+----+-------------+------------+--------------------+-----------------+

答案 2 :(得分:0)

这段代码似乎正在运作:

SELECT 
dense_rank() over (partition by AON_EMPL_ID 
order by AON_EMPL_ID,HR_DEPT_ID,Transfer_StartDate) RN,
TW.AON_EMPL_ID,TW.HR_DEPT_ID,TW.Transfer_Startdate,Effective_BDate from 
TT_AON_EMPLOYEE_WORKDAY TW
where TW.HR_DOMAIN_CODE = 'SGP'

显然,我只需要通过AON_EMPL_ID进行分区,其他所有内容都应该转到Order By子句。