MySQL:为什么日期差异总是0?

时间:2016-12-26 19:33:21

标签: mysql

我正在练习我的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()函数的值。 有人可以帮助我打破这个循环吗?

8 个答案:

答案 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