简体   繁体   中英

SQL Selecting Max and Min Dates in Different Rows

Thanks for your time! For each user, I am looking to output a single column which contains their earliest effective date and latest end date, along with other columns from this and other tables (this stuff is consistent for each user). Below is the format for the input data.

User   Eff_Date     End_Date    Otherstuff...
----|-------------|------------|---------
001 | 20140101    | 20140106
001 | 20140107    | 99990101
002 | 20140201    | 20140305
002 | 20140306    | 20140319
002 | 20140320    | 99990101
003 | 20140401    | 20140402
004 | 20140501    | 20250901

This is basically what I would prefer as a result:

User   Eff_Date     End_Date    Otherstuff...
----|-------------|------------|---------
001 | 20140101    | 99990101
002 | 20140201    | 99990101
003 | 20140401    | 20140402
004 | 20140501    | 20250901

Here is what I tried:

SELECT DISTINCT M.user, T.mineffdate, T.maxenddate, A.otherstuff


FROM tbluser M
LEFT JOIN otherstuff A ON A.[user]=M.[user]
INNER JOIN (SELECT user, MAX(m.end_date) as maxenddate, MIN(m.eff_date) as mineffdate FROM tbluser M GROUP BY user) T ON T.user = M.user AND T.maxenddate = m.end_date AND T.mineffdate = M.eff_date

When I ran this, users like 003 and 004 above showed up alright, but users like 001 and 002 failed to show up at all.

I am fairly new to SQL, so I might be making a very basic mistake. Feel free to let me know if that is the case. Additionally, I have no control over the data source, so I cannot fix this at the source. The only reason I found about about this was by using SQL to output every user record and then using VBA to assemble the records. This is unfortunately not a long-term solution.

Please let me know if you need any more info, and I appreciate everything, a nudge in the right direction might be enough to help me solve this. Thank you again for your time!

How about using windowing functions?

Try this:

Select distinct t.[user],
Min(t.eff_date) Over (Partition By [user]) as EffDate,
Max(t.End_Date) Over (Partition By [user]) as EndDate,
'Other' as [Other]
From tblUser t

EDIT: Although keep in mind if the dates are stored as strings MIN/MAX will work on the strings, not the dates. May need to convert to Date if they're stored as strings.

Try to use where NOT EXISTS clause, the example may not be exactly what you want, but showing the clause which may help you

SELECT M.user, M.Eff_Date, M.End_Date, M.otherstuff
FROM tbluser M
WHERE NOT EXISTS(
  SELECT * FROM tbluser N
  WHERE M.user=N.user AND (N.Eff_Date > M.Eff_Date OR N.Eff_Date = M.Eff_Date AND N.End_Date > M.End_Date)
)

this should work:

SELECT M.user, M.mineffdate, M.maxenddate, M.otherstuff, a.otherstuff
FROM (SELECT USER, MAX(m.end_date) as maxenddate, 
                   MIN(m.eff_date) as mineffdate,
                   MIN(otherstuff) AS minotherstuff
      from tbluser
      group by user) M
LEFT JOIN otherstuff A ON A.[user]=M.[user]

This is my quick solution for the problem

WITH MinTable As(
SELECT [User],MIN(Eff_Date) Eff_Date  FROM Test GROUP BY [User]),
MaxTable As(
SELECT [User],Max(End_Date) End_Date FROM Test GROUP BY [User])
SELECT MinTable.[User], MinTable.Eff_Date, MaxTable.End_Date FROM MinTable INNER JOIN MaxTable ON MinTable.[User] = MaxTable.[User]

Try this.

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