我正在练习我的SQL技能,这是我正在练习的问题: https://www.hackerrank.com/challenges/projects
问题在于:
您将获得一个表,Projects,包含三列:Task_ID, Start_Date和End_Date。它保证了它们之间的区别 对于每一行,End_Date和Start_Date等于1天 表。如果任务的End_Date是连续的,那么它们是 同一个项目的一部分。萨曼莎有兴趣找到总数 完成了不同项目的数量。
编写查询以输出列出的项目的开始和结束日期 按升序完成项目所需的天数。 如果有多个项目具有相同的数量 完成日期,然后按项目开始日期排序。
我的逻辑是,我会按开始日期排序所有内容,然后为每一行分配排名。如果当前结束日期是从上一个结束日期连续,也就是datediff(end_date,@ e)= 1,那么我将保持相同的排名,否则我将排名增加1.那么基本上所有行都属于对同一个项目将具有相同的排名。
以下是我的代码:
set @r := 0;
select min(start_date), max(end_date)
from (select start_date, end_date,
@r := if(datediff(end_date, @e) = 1, @r, @r+1) ranking,
@e := end_date
from projects
order by start_date
) b
group by ranking
order by datediff(max(end_date), min(start_date)), 1
;
但是这段代码不起作用。
更新
根据Sasha Pachev的回答进行更改后,当我尝试检查子查询时:
set @r = 0;
select start_date, end_date,
@e := end_date, datediff(end_date, date(@e)),
@r := if(datediff(end_date, date(@e)), @r, @r+1) ranking
from projects
order by start_date
;
我注意到我所有的日期差异都是0:
2015-10-01 2015-10-02 2015-10-02 0 1
2015-10-02 2015-10-03 2015-10-03 0 2
2015-10-03 2015-10-04 2015-10-04 0 3
2015-10-04 2015-10-05 2015-10-05 0 4
2015-10-11 2015-10-12 2015-10-12 0 5
2015-10-12 2015-10-13 2015-10-13 0 6
2015-10-15 2015-10-16 2015-10-16 0 7
2015-10-17 2015-10-18 2015-10-18 0 8
2015-10-19 2015-10-20 2015-10-20 0 9
我理解为什么,因为我在分配排名@r之前将@e指定为结束日期。但是如果我在@r之后分配@e,它就不起作用,因为我需要@e来获得diffdate()函数的值。 有人可以帮助我打破这个循环吗?
答案 0 :(得分:0)
分配/使用用户变量的顺序很重要。尝试:
select start_date, end_date,@e := end_date, datediff(end_date, date(@e)),
@r := if(end_date-@e = 1, @r, @r+1) ranking,
from projects
order by start_date
;
首先分配到@e
,然后在datediff()
答案 1 :(得分:0)
感谢Sasha Pachev提出一些很好的建议!
在这里表达我的问题无疑让我更清楚地思考。我已经坚持了两天这个问题,现在我刚刚达到顿悟......
我终于明白了我的问题的根本原因,并找到了解决方法。我最大的问题是我最初没有设置@e,所以当我在@r之前分配@e时,日期差异总是为0! (当然,因为它只是减去自己)。如果我在@r之后分配@e那么它总是为NULL。
以下是我的代码正常工作,希望这也有助于某人:
set @r = 0;
set @e = (select max(end_date) from projects);
select min(start_date), max(end_date)
from (
select start_date, end_date,
@r := if(datediff(end_date, date(@e)) = 1, @r, @r+1) ranking,
@e := end_date
from projects
order by start_date
) b
group by ranking
order by datediff(max(end_date), min(start_date)), 1
;
答案 2 :(得分:0)
您可以使用此类查询执行此操作。您可以直接在查询中执行变量的初始化:
SELECT min(start_date), max(end_date)
FROM (select start_date, end_date,
@r := if(datediff(end_date, @e) = 1, @r, @r+1) ranking,
@e := end_date as ee
FROM projects
CROSS JOIN ( SELECT @r:=0, @e:='1970-01-01') as init
ORDER BY start_date
) b
GROUP BY ranking
ORDER BY datediff(max(end_date), min(start_date));
示例输出
2015-10-15 2015-10-16
2015-10-17 2015-10-18
2015-10-19 2015-10-20
2015-10-21 2015-10-22
2015-11-01 2015-11-02
2015-11-17 2015-11-18
2015-10-11 2015-10-13
2015-11-11 2015-11-13
2015-10-01 2015-10-05
2015-11-04 2015-11-08
2015-10-25 2015-10-31
答案 3 :(得分:0)
这将起作用
SELECT SD,ED
FROM
(SELECT MIN(START_DATE) SD, MAX(END_DATE) ED, ( MAX(END_DATE)-MIN(START_DATE)) dd
FROM
(
SELECT START_DATE, END_DATE, END_DATE - ROW_NUMBER() OVER (ORDER BY END_DATE) DIST
FROM PROJECTS
ORDER BY 1)
GROUP BY DIST
ORDER BY 3,1);
答案 4 :(得分:0)
SELECT Start_Date, min(End_Date)
FROM
(SELECT Start_Date FROM Projects WHERE Start_Date NOT IN (SELECT End_Date FROM Projects)) a ,
(SELECT End_Date FROM Projects WHERE End_Date NOT IN (SELECT Start_Date FROM Projects)) b
WHERE Start_Date < End_Date
GROUP BY Start_Date
ORDER BY DATEDIFF(min(End_Date), Start_Date) ASC, Start_Date ASC;
答案 5 :(得分:0)
/* Below is my Solution */
select Min_Start_Date,Max_End_Date
from (
select distinct
min(start_date) over (partition by Ref_Start_date) as Min_Start_Date,
max(End_Date) over (Partition by Ref_End_Date) as Max_End_Date,
count(*) over (partition by Ref_Start_date,Ref_End_Date) as CNT
from (
select
start_date,
start_date+dense_rank() over (order by start_date desc) as Ref_Start_date,
end_date,
End_date+dense_rank() over (order by End_date desc) as Ref_End_date
from projects
)
order by 3,1
);
答案 6 :(得分:0)
SELECT START_DATE, MIN(END_DATE) AS [END_DATE]
FROM (
(SELECT START_DATE
FROM PROJECTS
WHERE START_DATE NOT IN (SELECT END_DATE FROM PROJECTS)
) A
CROSS JOIN
(SELECT END_DATE
FROM PROJECTS
WHERE END_DATE NOT IN (SELECT START_DATE FROM PROJECTS)
) B
)
WHERE START_DATE < END_DATE
GROUP BY START_DATE
ORDER BY DATEDIFF(DAY, MIN(END_DATE), START_DATE) DESC, CAST(START_DATE AS DATE) ASC
答案 7 :(得分:0)
select start_Date,end_date from (
select start_Date,end_date,datediff(day,start_Date,end_date)as diff1 from
(
select start_Date,row_number() over (order by start_Date) as rn from
(select start_date from projects
where start_date not in (select distinct end_date from projects)
) t1)t1a
left join
(select end_date,row_number() over (order by end_date) as rn from
(select end_date from projects
where end_date not in (select distinct start_date from projects)
) t2)t2a
on t1a.rn=t2a.rn )tx
order by diff1 , start_date