问题
I need to create a select query for a table which merges the rows per group on the 'Number' column to get a single row with all available yet latest (By ID) columns.
Here's what I mean, I need to take a table like this:
ID | Number | Date 1 | Date 2 | Date 3 |
----------------------------------------------------
1 | 1 | 2011-10-01 | NULL | NULL |
2 | 1 | NULL | 2011-10-25 | NULL |
3 | 1 | NULL | NULL | 2011-11-13 |
4 | 1 | 2011-10-03 | NULL | 2011-11-10 |
5 | 2 | NULL | NULL | 2012-01-01 |
6 | 2 | 2012-03-11 | NULL | NULL |
And return this (The ID column being unrelated to the above ID column):
ID | Number | Date 1 | Date 2 | Date 3 |
----------------------------------------------------
1 | 1 | 2011-10-03 | 2011-10-25 | 2011-11-10 |
2 | 2 | 2012-03-11 | NULL | 2012-01-01 |
So for all rows in each Group By the 'Number' column, I need all available column values from all rows in the group, but only the latest value for each column. The latest being determined by the highest value of 'ID' where a value in the column exists. (If no value in the column exists on any row in the group, then a value of Null is used).
Thanks
回答1:
You could use a subquery to select distinct numbers. Then for each number, you could look up the various columns in another subquery. The subquery would look for the row with the highest ID
where that particular column is not null.
select yt.Number
, (
select top 1 [Date 1]
from YourTable d1
where d1.Number = yt.Number
and d1.[Date 1] is not null
order by
d1.ID desc
) as [Date 1]
, (
select top 1 [Date 2]
from YourTable d2
where d2.Number = yt.Number
and d2.[Date 2] is not null
order by
d1.ID desc
) as [Date 2]
, ...
from (
select distinct Number
from YourTable
) as yt
回答2:
Thanks for everyone's suggestions. Unfortunately, I have been unable to make any of the current answers work for me. Unfortunately I cannot rely on the use of aggregate functions for the date as they may not be the max or min values. The use of a subquery per date column was very clever, but I was not been able to make the query run fast enough for my uses. (It needs to run almost instantly, but despite configuring indexes properly, was talking an in-ordinate amount of time.)
The solution I have come up with, is to create a new table with a structure to hold the results, then keep this table up to date with a number of triggers. The actual table in question is updated periodically, and the inserts into the table should allow me to keep a separate table up to date with triggers, thus giving me what I need.
回答3:
This deepends on your data, you can use the aggregate functions too.*
If your data always has nulls in the other rows, the aggregate functions will ignore them. This means you can use GROUP BY to get a single row.
SELECT ID, Number, MAX(Date1), MAX(Date2), MAX(Date3)
FROM MyTable
GROUP BY ID, Number
*NOTE: This will only work if you know you always want the MAX (or MIN) of the values of course. In your question you state that you want the one with the highest ID, so my solution may not work.
回答4:
The "ID" number you are looking for appears to be simple sequential representing the final "row" number of the result set (as you indicated has no bearing on the original ID column). So, taking into consideration a previous answer by Cylindric, just expand a little bit...
select
@FinalRow := @FinalRow +1 as ID,
PreQuery.*
from
( SELECT
Number,
MAX(Date1),
MAX(Date2),
MAX(Date3)
FROM
MyTable
GROUP BY
Number
ORDER BY
Number ) PreQuery,
(select @FinalRow := 0 ) SQLVars
来源:https://stackoverflow.com/questions/8325121/mysql-merge-row-values-into-single-row