11

I have a contracts table:

contractId    date       price     partId
1             20120121   10        1
2             20110130   9         1
3             20130101   15        2
4             20110101   20        2

The contract with greatest date being the active contract (don't blame me, I blame infor for creating xpps)

I need to create query to see only active contracts (one contract per part, the contract with highest date).

So the result of the query should be like this:

contractId    date       price     partId
1             20120121   10        1
3             20130101   15        2

I am out of ideas here, I tried self joining the table, I tried aggregation functions, but I can't figure it out. If anyone would have any idea, please share them with me..

4
  • 1
    What rdbms like MySql or Sql-Server are you using? Commented Nov 29, 2012 at 17:02
  • 1
    query is just fine with just a single r ... Commented Nov 29, 2012 at 17:03
  • 1
    I am sorry for that mistake, i am a little bit tired sitting whole day in front of telnet emulator trying to figure out this querry.. I am using the DB/2 on IBM AS/400. Commented Nov 29, 2012 at 17:08
  • Based on the tags, the dbms is officially "DB2 for i". (The system is currently known as IBM PowerSystem running IBM i. They haven't sold an AS/400 since 2000.) Commented Nov 29, 2012 at 21:55

3 Answers 3

19

this will work on almost all RDBMs,

SELECT  a.*
FROM    tableName A
        INNER JOIN
        (
            SELECT partID, MAX(date) maxDate
            FROM    tableName
            GROUP BY partID
        ) B on a.partID = b.partID AND
                a.date = b.maxDate

if your RDBMS supports Window Function,

SELECT  contractId ,date, price,partId
FROM    
(
    SELECT contractId ,date, price,partId,
            ROW_NUMBER() OVER (PARTITION BY PartID
                                ORDER BY date DESC) rn
    FROM    tableName
) s
WHERE   rn = 1
Sign up to request clarification or add additional context in comments.

Comments

5

This is the fast self join:

SELECT c1.*  FROM contracts c1   
LEFT OUTER JOIN contracts c2 ON c2.partId = c1.partId AND c1.date < c2.date 
WHERE c2.contractId IS NULL

The use of sub selects (nested selects) tend to be slower.

Comments

3
SELECT c.*
FROM contracts c
    INNER JOIN 
    (
        SELECT partId, MAX([date]) AS MaxDate
        FROM contracts
        GROUP BY partID
    ) MaxDate
        ON c.partId = MaxDate.partID
            AND c.[date] = MaxDate.[date]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.