Question

I have this query

SQL query: selecting by branch and machine code, order by branch and date

SELECT  
    mb.machine_id AS 'MachineId',
    MAX(mb.date) AS 'Date',
    mi.branch_id AS 'BranchId',
    b.branch AS 'Branch',
    b.branch_code AS 'BranchCode'
FROM
    dbo.machine_beat mb
    LEFT JOIN dbo.machine_ids mi
    ON mb.machine_id = mi.machine_id
    LEFT JOIN dbo.branches b
    ON mi.branch_id = b.lookup_key
GROUP BY 
    mb.machine_id,
    mi.branch_id,
    b.branch,
    b.branch_code
ORDER BY 
    b.branch, [Date] DESC

Query result:

|==========|=======================|=========|==========|==========|
|MachineId |Date                   |BranchId |Branch    |BranchCode|
|==========|=======================|=========|==========|==========|
|SS10000005|2014-03-31 19:10:17.110|3        |Mamamama  |MMMM      |
|SS10000043|2014-03-31 17:16:32.760|3        |Mamamama  |MMMM      |
|SS10000005|2014-02-17 14:58:42.523|3        |Mamamama  |MMMM      |
|==================================================================|

My problem is how to select the updated machine code? Expected query result:

|==========|=======================|=========|==========|==========|
|MachineId |Date                   |BranchId |Branch    |BranchCode|
|==========|=======================|=========|==========|==========|
|SS10000005|2014-03-31 19:10:17.110|3        |Mamamama  |MMMM      |
|==================================================================|

Update I created sqlfiddle. I also added data, aside from MMMM. I need the updated date for each branch. So probably, my result will be:

|==========|=======================|=========|==========|==========|
|MachineId |Date                   |BranchId |Branch    |BranchCode|
|==========|=======================|=========|==========|==========|
|SS10000343|2014-06-03 13:43:40.570|1        |Cacacaca  |CCCC      |
|SS30000033|2014-03-31 18:59:42.153|8        |Fafafafa  |FFFF      |
|SS10000005|2014-03-31 19:10:17.110|3        |Mamamama  |MMMM      |
|==================================================================|
Was it helpful?

Solution

@861051069712110711711710997114 is looking in the right direction - this is a question. Yours is more complicated than the usual because the greatest portion is coming from a different table than the group portion. The only issue with his answer is that you hadn't provided sufficient information to finish it correctly.

The following solves the problem:

WITH Most_Recent_Beat AS (SELECT Machine.branch_id,
                                 Beat.machine_id, Beat.date,
                                 ROW_NUMBER() OVER(PARTITION BY Machine.branch_id 
                                                   ORDER BY Beat.date DESC) AS rn
                          FROM machine_id Machine
                          JOIN machine_beat Beat
                            ON Beat.machine_id = Machine.machine_id)
SELECT Beat.machine_id, Beat.date,
       Branches.lookup_key, Branches.branch, Branches.branch_code
FROM Branches
JOIN Most_Recent_Beat Beat
  ON Beat.branch_id = Branches.lookup_key
     AND Beat.rn = 1
ORDER BY Branches.branch, Beat.date DESC

(and corrected SQL Fiddle for testing. You shouldn't be using a different RDBMS for the example, especially as there were syntax errors for the db you say you're using.)

Which yields your expected results.

So what's going on here? The key is the ROW_NUMBER()-function line. This function itself simply generates a number series. The OVER(...) clause defines what's known as a window, over which the function will be run. PARTITION BY is akin to GROUP BY - every time a new group occurs (new Machine.branch_id value), the function restarts. The ORDER BY inside the parenthesis simply says that, per group, entries should have the given function run on entries in that order. So, the greatest date (most recent, assuming all dates are in the past) gets 1, the next 2, etc.
This is done in a CTE here (it could also be done as part of a subquery table-reference) because only the most recent date is required - where the generated row number is 1; as SQL Server doesn't allow you to put SELECT-clause aliases into the WHERE clause, it needs to be wrapped in another level to be able to reference it that way.

OTHER TIPS

Try using Row_number with partition by

     select * from 
        (
        SELECT  
            mb.machine_id AS 'MachineId',
            mb.date AS 'Date',
            mi.branch_id AS 'BranchId',
            b.branch AS 'Branch',
            b.branch_code AS 'BranchCode',rn=row_number()over(partition by mb.machine_id order by mb.date desc)
        FROM
            dbo.machine_beat mb
            LEFT JOIN dbo.machine_ids mi
            ON mb.machine_id = mi.machine_id
            LEFT JOIN dbo.branches b
            ON mi.branch_id = b.lookup_key
        WHERE 
            branch_code = 'MMMM'
/*
        GROUP BY 
            mb.machine_id,
            mi.branch_id,
            b.branch,
            b.branch_code
*/
        )x

    where x.rn=1
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top