简体   繁体   中英

How can I subtract two row's values within same column with getting latest record of date using sql query?

I want to display the subtraction of the latest record in stage 2 and the latest record in stage 3 This is the table structure:

   ------------------------------------
      name |stage| date
   ------------------------------------
    | ABC  | 2   | 2016-5-07
    | ABC  | 2   | 2016-6-08  
    | ABC  | 3   | 2016-6-07
    | ABC  | 3   | 2016-12-08 
    | PQR  | 2   | 2016-6-07
    | PQR  | 2   | 2016-8-12  
    | PQR  | 3   | 2016-9-07
    | PQR  | 3   | 2016-10-08 

I want to subtract date 2016-6-08 from date 2016-12-08 where name is ABC, they will be 183 days And subtract 2016-8-12 from 2016-10-08 where name is PQR

Output should be like as

| name | Date |
 ---------------
| ABC  | 183  |
| PQR  | 61   |
WITH cte AS (
    SELECT t.[name], t.[stage], t.[date]
    FROM
    (
        SELECT [name], [stage], [date],
               ROW_NUMBER() OVER (PARTITION BY [name], [stage] ORDER BY [date] DESC) rn
    ) t
    WHERE t.rn = 1
)

SELECT [name], DATEDIFF(day, MIN(t.[date]), MAX(t.[date])) AS [Date]
FROM cte t
GROUP BY [name]
SELECT [NAME], DATEDIFF(DAY, MIN(x.[DATE]), MAX(x.[DATE])) AS [DATE]
FROM
    (SELECT T.[NAME], T.[STAGE], T.[DATE]
    FROM
    (
        SELECT [NAME], [STAGE], [DATE],
               ROW_NUMBER() OVER (PARTITION BY [NAME], [STAGE] ORDER BY [DATE] DESC) RN FROM #TABLE3
    ) T
    WHERE T.RN = 1
)X
GROUP BY [NAME]

or

SELECT NAME, DATEDIFF(DD,MIN([DATE]),MAX([DATE])) AS [DATE] FROM 
(SELECT NAME, STAGE, MAX([DATE]) AS [DATE] FROM #TABLE3 GROUP BY NAME, STAGE) C
 GROUP BY NAME;
with cte as (
select name, stage, max([date]) as [date] from #YourTable group by name, stage
)
select name, datediff(dd,min([date]),max([date])) as [Date] from cte group by name;

The other answers are subtracting the minimum and maximum dates ignoring stage, instead of the max dates from each stage. Try this:

SELECT s2.name, DATEDIFF(day, MAX(s2.date), MAX(s3.date)) days
  FROM MyTable s2 JOIN MyTable s3 ON s2.name = s3.name
 WHERE s2.stage = 2 AND s3.stage = 3
 GROUP BY s2.name;

The JOIN combines two copies of the table into a single big table that has a row for every combination of two rows with the same name in the original table.

 name | s2.stage |  s2.date   | s3.stage |  s3.date
------+----------+------------+----------+------------
 ABC  |        2 | 2016-06-08 |        2 | 2016-06-08
 ABC  |        2 | 2016-06-08 |        3 | 2016-06-07
 ABC  |        2 | 2016-06-08 |        3 | 2016-12-08
 ABC  |        2 | 2016-06-08 |        2 | 2016-05-07
 ABC  |        3 | 2016-06-07 |        2 | 2016-06-08
 ABC  |        3 | 2016-06-07 |        3 | 2016-06-07
 ABC  |        3 | 2016-06-07 |        3 | 2016-12-08
 ABC  |        3 | 2016-06-07 |        2 | 2016-05-07
 ABC  |        3 | 2016-12-08 |        2 | 2016-06-08
 ABC  |        3 | 2016-12-08 |        3 | 2016-06-07
 ABC  |        3 | 2016-12-08 |        3 | 2016-12-08
 ABC  |        3 | 2016-12-08 |        2 | 2016-05-07
 ABC  |        2 | 2016-05-07 |        2 | 2016-06-08
 ABC  |        2 | 2016-05-07 |        3 | 2016-06-07
 ABC  |        2 | 2016-05-07 |        3 | 2016-12-08
 ABC  |        2 | 2016-05-07 |        2 | 2016-05-07
 PQR  |        2 | 2016-08-12 |        2 | 2016-08-12
 PQR  |        2 | 2016-08-12 |        3 | 2016-09-07
 PQR  |        2 | 2016-08-12 |        3 | 2016-10-08
 PQR  |        2 | 2016-08-12 |        2 | 2016-06-07
 PQR  |        3 | 2016-09-07 |        2 | 2016-08-12
 PQR  |        3 | 2016-09-07 |        3 | 2016-09-07
 PQR  |        3 | 2016-09-07 |        3 | 2016-10-08
 PQR  |        3 | 2016-09-07 |        2 | 2016-06-07
 PQR  |        3 | 2016-10-08 |        2 | 2016-08-12
 PQR  |        3 | 2016-10-08 |        3 | 2016-09-07
 PQR  |        3 | 2016-10-08 |        3 | 2016-10-08
 PQR  |        3 | 2016-10-08 |        2 | 2016-06-07
 PQR  |        2 | 2016-06-07 |        2 | 2016-08-12
 PQR  |        2 | 2016-06-07 |        3 | 2016-09-07
 PQR  |        2 | 2016-06-07 |        3 | 2016-10-08
 PQR  |        2 | 2016-06-07 |        2 | 2016-06-07

The WHERE s2.stage=2 AND s3.stage=3 restricts it to the rows where the s2 columns correspond to stage 2 and the s3 columns to stage 3:

 name | s2.stage | s2.date    | s3.stage |    s3.date
------+----------+------------+----------+------------
 ABC  |        2 | 2016-05-07 |        3 | 2016-06-07
 ABC  |        2 | 2016-05-07 |        3 | 2016-12-08
 ABC  |        2 | 2016-06-08 |        3 | 2016-06-07
 ABC  |        2 | 2016-06-08 |        3 | 2016-12-08
 PQR  |        2 | 2016-06-07 |        3 | 2016-09-07
 PQR  |        2 | 2016-06-07 |        3 | 2016-10-08
 PQR  |        2 | 2016-08-12 |        3 | 2016-09-07
 PQR  |        2 | 2016-08-12 |        3 | 2016-10-08

We then take the maximum value of each date field for each name by using the MAX(...) function and a GROUP BY name clause, and subtract them using the DATEDIFF function.

As a note, you should tag the question with the specific database you're using; the above SQL works in Microsoft SQL Server, but other databases do date difference differently and support a JOIN ... USING syntax that would simplify the query slightly. For instance, this is what it would look like in Postgres:

SELECT name, MAX(s3.date) - MAX(s2.date) days
  FROM MyTable s2 JOIN MyTable s3 USING (name)
 WHERE s2.stage = 2 AND s3.stage = 3
 GROUP BY name;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM