簡體   English   中英

SQL按日期分組沖突

[英]SQL Group By Date Conflicts

我有一個表,其中包含start_date和end_date列。 我們需要做的是為每個Object_ID選擇所有內容並按日期沖突將它們分組。

日期沖突是指一行的開始日期和/或結束日期經過另一行。 例如,以下是一些沖突示例:

第1行的日期為1至5,第2行的日期為2至3。

第1行的日期為2至5,第2行的日期為1至3。

第1行的日期為2至5,第2行的日期為3至6。

第1行的日期為2至5,第2行的日期為1至7。

因此,例如,如果我們有一些示例數據(為簡單起見,假設數字僅是一個月中的幾天):

id | object_id | start_date | end_date
1  | 1         | 1          | 5
2  | 1         | 2          | 4
3  | 1         | 6          | 8
4  | 2         | 2          | 3

我希望看到的是:

object_id | start_date | end_date | numconflicts
1         | <na>       | <na>     | 2
1         | 6          | 8        | 0 or null
2         | 2          | 3        | 0 or null

對於第二個測試用例,以下是一些示例數據:

id | object_id | start_date | end_date
1  | 1         | 1          | 5
2  | 1         | 2          | 4
3  | 1         | 6          | 8
4  | 2         | 2          | 3
5  | 2         | 4          | 5
6  | 1         | 2          | 3
7  | 1         | 10         | 12
8  | 1         | 11         | 13

對於第二個測試用例,我希望看到的輸出是:

object_id | start_date | end_date | numconflicts
1         | <na>       | <na>     | 3
1         | 6          | 8        | 0 or null
2         | 2          | 3        | 0 or null
2         | 4          | 5        | 0 or null
1         | <na>       | <na>     | 2

是的,我將需要區分第一組和第二組(第一行和最后一行)的方法,但我還沒有弄清楚。 目的是查看此列表,然后在單擊一組沖突時可以查看該組中的所有沖突。

我的第一個想法是嘗試使用GROUP BY CASE ...子句,但我只是被自己包裹着。

我用來呼叫mysql的語言是php。 因此,如果有人知道一個php循環解決方案,而不是一個大型的mysql查詢,我就會不知所措。

提前致謝。

編輯:在主鍵中添加以減少混亂。

編輯:在測試用例2中添加以提供更多推理。

該查詢查找重復項的數量:

select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
    on od2.object_id = od1.object_id
    and od2.end_date >= od1.start_date
    and od2.start_date <= od1.end_date
    and od2.id != od1.id
group by 1,2,3;

您可以將此查詢用作查詢的基礎,該查詢可以為您提供所需的確切信息(有關輸出,請參見下文)。

select
  object_id,
  case dups when 0 then start_date else '<na>' end as start_date,
  case dups when 0 then end_date else '<na>' end as end_date,
  sum(dups) as dups
from (
  select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
  from object_date od1
  left join object_date od2
    on od2.object_id = od1.object_id
    and od2.end_date >= od1.start_date
    and od2.start_date <= od1.end_date
    and od2.id != od1.id
  group by 1,2,3) x
group by 1,2,3;

請注意,我使用了id列來區分行。 但是,您可以將id不匹配的測試替換為每列上的比較,即用其他每列都不相等的測試替換od2.id != od1.id ,但是這需要在所有其他列上使用唯一索引有意義,無論如何,擁有id列是一個好主意。

這是使用您的數據的測試:

create table object_date (
    id int primary key auto_increment,
    object_id int,
    start_date int,
    end_date int
);
insert into object_date (object_id, start_date, end_date) 
    values (1,1,5),(1,2,4),(1,6,8),(2,2,3);

針對此樣本數據運行時,第一個查詢的輸出:

+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
|         1 |          1 |        5 |    1 |
|         1 |          2 |        4 |    1 |
|         1 |          6 |        8 |    0 |
|         2 |          2 |        3 |    0 |
+-----------+------------+----------+------+

針對此樣本數據運行時第二個查詢的輸出:

+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
|         1 | 6          | 8        |    0 |
|         1 | <na>       | <na>     |    2 |
|         2 | 2          | 3        |    0 |
+-----------+------------+----------+------+

Oracle:這可以通過CASE語句在組中的子查詢來完成。

https://forums.oracle.com/forums/thread.jspa?threadID=2131172

Mysql:您可能會看到所有沖突的視圖。

從約會a1和約會a2中選擇不同的a1.appt,a2.appt,其中a1.start <a2.end和a1.end> a2.start。

然后只需對該表執行count(*)。

類似於以下內容的東西應該起作用:

select T1.object_id, T1.start_date, T1.end_date, count(T1.object_id) as numconflicts
from T1
inner join T2 on T1.start_date between T2.start_date and T2.end_date
inner join T3 on T1.end_date between T2.start_date and T2.end_date
group by T1.object_id

我可能會有點不舒服,但這應該可以幫助您入門。

編輯 :正確縮進

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM