Question

I have this table

CREATE TABLE staff (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(32),
  `surname` varchar(32),
  `dateEnrollment` date,
  `dateCompletion` date,
  PRIMARY KEY (`id`)
);

INSERT INTO staff (`firstname`, `surname`, `dateEnrollment`, `dateCompletion`) VALUES
('Demo', 'Demo', '2010-01-13', '2010-02-13'),
('Jone', 'Borek', '2010-02-14', '2011-03-13'),
('Denis', 'Koszi', '2010-02-15', '2010-06-13');

And I need to SQL query that returns my longest period without any activity. Eg: Jone Borek Completetion 2011-03-13 to Denis Koszi Completion 2010-06-13 - in this period was company without activity... How can I achieve it? Many thanks for help

Was it helpful?

Solution

Either of the following will work, (I prefer the latter):

SELECT 
MAX(DATEDIFF(
(SELECT MIN(s2.dateCompletion) 
    FROM staff s2 
    WHERE s2.dateCompletion >= s.dateCompletion AND s2.id != s.id)
, dateCompletion))
from staff s;

In the above example, for each record, you find the next completed project, do a datediff, and then take the max.

In the example below, I use joins to do the same thing. If you're dataset is really big, you might be better off creating a temporary table and get rid of the derived table.

SELECT
MAX(DATEDIFF(s2.dateCompletion, s.dateCompletion))
FROM staff s
JOIN staff s2 ON s2.dateCompletion = (SELECT MIN(s3.dateCompletion) 
    FROM staff s3 
    WHERE s3.dateCompletion >= s.dateCompletion
      AND s3.id != s.id)

Also, as you're measuring maximum period of inactivity, would you also like to include the date difference between the MAX(dateCompletion) and CURDATE(), then use the following:

SELECT
MAX(DATEDIFF(COALESCE(s2.dateCompletion, CURDATE()), s.dateCompletion))
FROM staff s
JOIN staff s2 ON s2.dateCompletion = (SELECT MIN(s3.dateCompletion) 
    FROM staff s3 
    WHERE s3.dateCompletion >= s.dateCompletion
      AND s3.id != s.id)

OTHER TIPS

Try:

SELECT s1.id id1,
       s1.firstname firstname1,
       s1.surname surname1,
       s1.`dateCompletion` dateCompletion1,
       s2.id id2,
       s2.firstname firstname2,
       s2.surname surname2,
       s2.`dateCompletion` dateCompletion2,
       datediff( s1.`dateCompletion`, s2.`dateCompletion` )
FROM staff s1
JOIN staff s2
ON s1.`dateCompletion` = (
        SELECT min(dateCompletion)
        FROM staff s3
        WHERE s3.dateCompletion > s2.`dateCompletion`
  ) 
ORDER BY datediff( s2.`dateCompletion`, s1.`dateCompletion` )
LIMIT 1

demo: http://sqlfiddle.com/#!2/c1e939/8

select x.firstname as firstname1,x.surname as surname1,y.firstname as firstname2,y.surname as surname2,MIN(ABS(DATEDIFF(x.dateEnrollment,x.dateCompletion)-DATEDIFF(y.dateEnrollment,y.dateCompletion))) AS parameter
    from staff x join staff y on 
    x.dateEnrollment <= y.dateCompletion and y.dateEnrollment <= x.dateCompletion and x.firstname!=y.firstname and x.surname!=y.surname

This will give the details of the two people along with the parameter value which should be minimum for the two to have stayed for the longest time if that's what your question meant. You can also add dates in the result if you want.

Also a quicker way will be to use it with having clause:

 select x.firstname as firstname1,x.surname as surname1,y.firstname as firstname2,y.surname as surname2
    from staff x join staff y on 
    x.dateEnrollment <= y.dateCompletion and y.dateEnrollment <= x.dateCompletion and x.firstname!=y.firstname and x.surname!=y.surname HAVING MIN(ABS(DATEDIFF(x.dateEnrollment,x.dateCompletion)-DATEDIFF(y.dateEnrollment,y.dateCompletion)))

Hope it helps!!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top