2016-04-23 12 views
5

Tôi có một tập hợp con của hồ sơ mà trông như thế này:Cách nhận ngày tối thiểu tiếp theo không phải trong vòng 30 ngày và sử dụng làm điểm tham chiếu trong SQL?

ID DATE 
A 2015-09-01 
A 2015-10-03 
A 2015-10-10 
B 2015-09-01 
B 2015-09-10 
B 2015-10-03 
... 

Đối với mỗi ID ngày tối thiểu đầu tiên là kỷ lục chỉ số đầu tiên. Bây giờ tôi cần phải loại trừ các trường hợp trong vòng 30 ngày kể từ ngày hồ sơ chỉ mục và bất kỳ bản ghi nào có ngày lớn hơn 30 ngày trở thành một bản ghi chỉ mục khác.

Ví dụ: đối với ID A, 2015-09-01 và 2015-10-03 là cả bản ghi chỉ mục và sẽ được giữ lại vì chúng cách nhau hơn 30 ngày. 2015-10-10 sẽ bị loại bỏ vì trong vòng 30 ngày kể từ ngày trường hợp chỉ mục thứ 2.

Đối với ID B, 2015-09-10 sẽ bị xóa và KHÔNG phải là trường hợp chỉ mục vì trong vòng 30 ngày kể từ ngày kỷ lục chỉ mục đầu tiên. 2015-10-03 sẽ được giữ lại vì nó lớn hơn 30 ngày của hồ sơ chỉ số thứ nhất và sẽ được coi là trường hợp chỉ mục thứ 2.

Đầu ra nên trông như thế này:

ID DATE 
A 2015-09-01 
A 2015-10-03 
B 2015-09-01 
B 2015-10-03 

Làm thế nào để làm điều này trong SQL server 2012? Không có giới hạn về số ngày ID có thể có, có thể chỉ là 1 đến 5 hoặc nhiều hơn. Tôi khá cơ bản với SQL nên mọi trợ giúp sẽ được đánh giá cao.

+0

Chúng tôi vẫn đang gặp sự cố? –

Trả lời

2

làm việc như trong ví dụ của bạn, #test là bảng của bạn với dữ liệu:

;with cte1 
as 
(
    select 
     ID, Date, 
     row_number()over(partition by ID order by Date) groupID 
    from #test 
), 
cte2 
as 
(
    select ID, Date, Date as DateTmp, groupID, 1 as getRow from cte1 where groupID=1 
    union all 
    select 
     c1.ID, 
     c1.Date, 
     case when datediff(Day, c2.DateTmp, c1.Date) > 30 then c1.Date else c2.DateTmp end as DateTmp, 
     c1.groupID, 
     case when datediff(Day, c2.DateTmp, c1.Date) > 30 then 1 else 0 end as getRow 
    from cte1 c1 
    inner join cte2 c2 on c2.groupID+1=c1.groupID and c2.ID=c1.ID 
) 
select ID, Date from cte2 where getRow=1 order by ID, Date 
+0

Điều này làm việc hoàn hảo !!! Cảm ơn bạn rất nhiều! Được đánh giá cao =) – KChan

-1

Hãy thử giải pháp này.

Sample demo

with diffs as (
select t1.id,t1.dt strtdt,t2.dt enddt,datediff(dd,t1.dt,t2.dt) daysdiff 
from t t1 
join t t2 on t1.id=t2.id and t1.dt<t2.dt 
) 
, y as (
select id,strtdt,enddt 
from (
select id,strtdt,enddt,row_number() over(partition by id,strtdt order by daysdiff) as rn 
from diffs 
where daysdiff > 30 
) x 
where rn=1 
) 
,z as (
select *,coalesce(lag(enddt) over(partition by id order by strtdt),strtdt) prevend 
from y) 
select id,strtdt from z where strtdt=prevend 
union 
select id,enddt from z where strtdt=prevend 
+0

tự hỏi nếu lý do có thể được giải thích cho downvote –

+0

Đã có một loạt các downvotes bằng cách nào đó. –

-1

Logic của bạn được giải thích trong câu hỏi là sai, tại một nơi, bạn đã biết lấy các bản ghi chỉ số đầu tiên và ở vị trí tiếp theo bạn coi kỷ lục ngay lập tức ..

này làm việc cho hồ sơ trực tiếp:

with cte 
as 
(
select *, ROW_NUMBER() over (partition by id order by datee) as rownum 
from #test 
) 
select *,datediff(day,beforedate,datee) 
from cte t1 
cross apply 
(Select isnull(max(Datee),t1.datee) as beforedate from cte t2 where t1.id =t2.id and t2.rownum<t1.rownum) b 
where datediff(day,beforedate,datee)= 0 or datediff(day,beforedate,datee)>=30 

này wo RKS cho kỷ lục cơ sở liên tục:

select *,datediff(day,basedate,datee) from #test t1 
cross apply 
(select min(Datee) as basedate from #test t2 where t1.id=t2.id)b 
where datediff(day,basedate,datee)>=30 or datediff(day,basedate,datee)=0 
+0

@ downvoters: xin vui lòng để lại một bình luận về lý do tại sao điều này đã được downvoted – TheGameiswar

0
select * from 
    (
    select ID,DATE_, case when DATE_DIFF is null then 1 when date_diff>30 then 1 else 0 end comparison from 
     (
      select ID, DATE_ ,DATE_-LAG(DATE_, 1) OVER (PARTITION BY ID ORDER BY DATE_) date_diff from trial 
     ) 
    ) 
    where comparison=1 order by ID,DATE_; 

Cố gắng trong cơ sở dữ liệu Oracle. Các chức năng tương tự cũng tồn tại trong SQL Server.

Tôi đang nhóm theo cột Id và dựa trên trường DATE, đang so sánh ngày trong trường hiện tại với trường trước đó của nó. Hàng đầu tiên của một id người dùng cụ thể sẽ trả về null và trường đầu tiên được yêu cầu trong đầu ra của chúng tôi làm chỉ mục đầu tiên. Đối với tất cả các lĩnh vực khác, chúng tôi quay trở lại 1 khi sự chênh lệch ngày đối với lĩnh vực trước với lớn hơn 30.

Lag function in transact sql

Case function in transact sql

+0

Là 'AS' trước khi bí danh bắt buộc trong SQL server?Trong trường hợp đó ORDER BY DATE_) AS date_diff –

+0

Đối với máy chủ SQL: chọn * từ ( ID chọn, DATE_, trường hợp khi DATE_DIFF là null thì 1 khi date_diff> 30 rồi 1 else 0 end AS so sánh từ ( chọn ID , DATE_, DATE_-LAG (DATE_, 1) OVER (PARTITION BY ID ORDER BY DATE_) AS date_diff từ thử nghiệm ) ) nơi so sánh = 1 theo ID, DATE_; –

+0

Cảm ơn, tôi đã thử điều này nhưng có lỗi cú pháp gần ')'. Một cách khác để đặt câu hỏi của tôi là, làm cách nào tôi có thể chỉ chọn các bản ghi cách nhau> = 30 ngày cho mỗi ID? Trong khi bỏ qua hoặc loại bỏ tất cả những cái ở giữa. – KChan

Các vấn đề liên quan