简体   繁体   中英

SQL Server 2008 How can I SELECT rows with Value by GROUP(ing) other column?

Hi guys I'm a beginner at SQL so please bear with me.. :)

My question is as follows.

I got this table:

     DateTime         ID     Year    Month   Value    Cost
-------------------|------|--------|-------|-------|--------|
 1-1-2013 00:00:01 |  1   |  2013  |   1   |  30   |   90   |
 1-1-2013 00:01:01 |  1   |  2013  |   1   |  0    |   0    |
 1-1-2013 00:02:01 |  1   |  2013  |   1   |  1    |   3    |
 1-2-2013 00:00:01 |  1   |  2013  |   2   |  2    |   6    |
 1-2-2013 00:01:01 |  1   |  2013  |   2   |  3    |   9    |
 1-2-2013 00:02:01 |  1   |  2013  |   2   |  4    |   12   |
 1-3-2013 00:00:01 |  1   |  2013  |   3   |  5    |   15   |
 1-3-2013 00:01:01 |  1   |  2013  |   3   |  6    |   18   |
 1-3-2013 00:02:01 |  1   |  2013  |   3   |  7    |   21   |

Now what I'm trying to get is this result

   Year    Month   Value    Cost
|--------|-------|-------|--------|
|  2013  |   1   |  1    |   3    |
|  2013  |   2   |  4    |   12   |
|  2013  |   3   |  7    |   21   |

As you can see I'm trying to GROUP BY the [Month] and the [Year] and to get the last [Value] for every [Month].

Now as you can understand from the result I do not try to get the MAX() value from the [Value] column but the last value for every [Month] and that is my issue..

Thanks in advance

PS
I was able to GROUP BY the [Year] and the [Month] but as I understand that when I adding the [Value] column the GROUP BY is not effecting the result, as the SQL need more spcification on the value you what the SQL to get..

Instead of using row_number() , you can also use rank() . Using rank() might give you multiple values within the same year and month, see this post . Because of this, a group by is added.

SELECT
  [Year],
  [Month],
  [Value],
  [Cost]
FROM
(
  SELECT 
    [Year],
    [Month],
    [Value],
    [Cost],
    Rank() OVER (PARTITION BY [Year], [Month] ORDER BY [DateTime] DESC) AS [Rank]
  FROM [t1]
) AS [sub]
WHERE [Rank] = 1
GROUP BY 
  [Year],
  [Month],
  [Value],
  [Cost]
ORDER BY
  [Year] ASC,
  [Month] ASC

As stated in the comments, this might still return multiple records for a single month. Therefor the ORDER BY statement can be extended, based on the desired functionality:

Rank() OVER (PARTITION BY [Year], [Month] ORDER BY [DateTime] DESC, [Value] DESC, [Cost] ASC) AS [Rank]

Switching the order of [Value] and [Cost] or ASC <> DESC will influence the rank and because of that the result.

Since you are using SQL Server 2008, you can use row_number() to get the result:

select year, month, value, cost
from
(
  select year, month, value, cost,
    row_number() over(partition by year, month order by datetime desc) rn
  from yourtable
) src
where rn = 1

See SQL Fiddle with Demo

Or you can use a subquery to get this ( note: with this version if you have more than one record with the same max datetime per month then you will return each record:

select t1.year, t1.month, t1.value, t1.cost
from yourtable t1
inner join
(
  select max(datetime) datetime
  from yourtable
  group by year, month
) t2
  on t1.datetime = t2.datetime

See SQL Fiddle with Demo

Both give the same result:

| YEAR | MONTH | VALUE | COST |
-------------------------------
| 2013 |     1 |     1 |    3 |
| 2013 |     2 |     4 |   12 |
| 2013 |     3 |     7 |   21 |

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