最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Create a slowly changing dimension in SQL Server using SQL query - Stack Overflow

programmeradmin0浏览0评论

I have an employee seating table and I have taken a snapshot of dummy data with out sharing the actual data

table data

I need a logic to convert this to this output

output table

How would I achieve this with just SQL?

I have tried few tricks but nothing is working

Here is the code to create the dataset just in case you need it

create table #test
(
    start_date date,
    end_date date,
    emp_id varchar(20),
    seating_type varchar(10)
)

create table #test
(
    start_date date,
    end_date date,
    emp_id varchar(20),
    seating_type varchar(10)
)

insert into #test
select '01-01-2025','01-10-2025','123','abc'
union
select '01-11-2025','01-20-2025','123','abc'
union
select '01-21-2025','01-31-2025','123','def'
union
select '02-01-2025','02-10-2025','123','abc'
union
select '02-11-2025','02-20-2025','123','def'
union
select '02-21-2025','02-28-2025','123','gih'
union
select '03-01-2025','03-10-2025','123','def'
union
select '02-10-2025','02-25-2025','456','def'
union
select '02-26-2025','03-10-2025','456','abc'
union
select '03-11-2025','03-27-2025','456','abc'
union
select '03-28-2025','04-10-2025','456','gih'

I have an employee seating table and I have taken a snapshot of dummy data with out sharing the actual data

table data

I need a logic to convert this to this output

output table

How would I achieve this with just SQL?

I have tried few tricks but nothing is working

Here is the code to create the dataset just in case you need it

create table #test
(
    start_date date,
    end_date date,
    emp_id varchar(20),
    seating_type varchar(10)
)

create table #test
(
    start_date date,
    end_date date,
    emp_id varchar(20),
    seating_type varchar(10)
)

insert into #test
select '01-01-2025','01-10-2025','123','abc'
union
select '01-11-2025','01-20-2025','123','abc'
union
select '01-21-2025','01-31-2025','123','def'
union
select '02-01-2025','02-10-2025','123','abc'
union
select '02-11-2025','02-20-2025','123','def'
union
select '02-21-2025','02-28-2025','123','gih'
union
select '03-01-2025','03-10-2025','123','def'
union
select '02-10-2025','02-25-2025','456','def'
union
select '02-26-2025','03-10-2025','456','abc'
union
select '03-11-2025','03-27-2025','456','abc'
union
select '03-28-2025','04-10-2025','456','gih'
Share Improve this question edited Mar 27 at 19:50 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Mar 27 at 17:32 PratPrat 233 bronze badges 7
  • You are just combining rows 1 and 2 (using the start date of row 1 and the end date for row 2). This combining seem to only occur if the rows are adjacent and of the same empt_id+seating_type. This is a gaps and island problem that requires us to create groups of uninterrupted empt_id+seating_type combinations. – Bart McEndree Commented Mar 27 at 17:47
  • in the example yes, but the ask is to get min startdate and max enddate for each instance(change) for the seatingtype – Prat Commented Mar 27 at 17:51
  • Please add more example rows with a different emp_id than 123 or remove the emp_id column as not important to the solution. – Bart McEndree Commented Mar 27 at 17:51
  • I am not sure what the ask is from you ? empid is required as the seating type is tagged to empid. I just shared one empid to keep it simple. Just creating a group using empid+seating_type will not solve the problem as in the sample you can see 'abc' seating type came again after 'def'. so we would need two rows for abc in the final output – Prat Commented Mar 27 at 17:57
  • Without multiple emp_id values I cannot be sure that my solution works for the full variety of examples you might have. – Bart McEndree Commented Mar 27 at 18:08
 |  Show 2 more comments

1 Answer 1

Reset to default 2

Generate island groups using 2 types of row number partitioning

WITH CTE as
(
SELECT *, 
      ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY start_date) rn,
      ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY start_date) -  ROW_NUMBER() OVER (PARTITION BY emp_id,Seating_Type ORDER BY start_date) grp
FROM #test
)
SELECT Min(start_date) as Start_date, max(end_date) as End_date, emp_id, seating_type
FROM CTE
GROUP BY grp,  emp_id, seating_type
ORDER BY min(rn)

fiddle

发布评论

评论列表(0)

  1. 暂无评论