Reputation: 129
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 |
|==================================================================|
Upvotes: 1
Views: 162
Reputation: 13046
@861051069712110711711710997114 is looking in the right direction - this is a greatest-n-per-group 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.
Upvotes: 1
Reputation: 7189
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
Upvotes: 2