Question

Unfortunately my knowledge related to statements like group by and having is quite limited, so hopefully you can help me:

I have a view - here's an excerpt - (if we have some Europeans here - it's v021 of Winline/Mesonic):

ID        | Artikelbezeichnung1                 | Bez2      | mesoyear
_____________________________________________________________________
1401MA70  | Marga ,Saracena grigio,1S,33,3/33,3 | Marazzi   | 1344
1401MA70  | Marga ,Saracena grigio,1S,33,3/33,3 | Marazzi   | 1356
1401MA70  | Marga ,Saracena grigio,1S,33,3/33,3 | Marazzi   | 1356
1401MA71  | Marga ,Saracena beige,1S,33,3/33,3  | Marazzi   | 1344
1401MA71  | Marga ,Saracena beige,1S,33,3/33,3  | Marazzi   | 1356
1401MA71  | Marga ,Saracena beige,1S,33,3/33,3  | Marazzi   | 1356    
2401CR13  | Crista,Mahon rojo,1S,33,3/33,3      | Cristacer | 1332    
2401CR13  | Crista,Mahon rojo,1S,33,3/33,3      | Cristacer | 1344

So the ID is not unique and I just need the one with the highest val in mesoyear.

My fist solution was:

Select 
    c015 as ID,
    c003 as Artikelbezeichnung1,
    c074 as Bez2,
    mesoyear
from 
    CWLDATEN_91.dbo.v021
group by 
    c015
having 
    mesoyear = max(mesoyear)

But this doesn't work at all...

Msg 8121, Level 16, State 1, Line 8
Column 'CWLDATEN_91.dbo.v021.mesoyear' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.

So I just removed the having statement and it went "better":

Msg 8120, Level 16, State 1, Line 2
Column 'CWLDATEN_91.dbo.v021.c003' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

So I tried to remove the error just by adding things to the "group by". And it worked.

Select 
    c015 as ID,
    c003 as Artikelbezeichnung1,
    c074 as Bez2,
    max(mesoyear)
from 
    CWLDATEN_91.dbo.v021
group by 
    c015, c003, c074

gives me exactly what I want.

But the correct select contains about 24 columns and some calculations as well. The problem can't be solved just by adding all the columns to the group by...?

Can someone please help me to find a proper command?

Thank you!

Was it helpful?

Solution

You don't actually want group by. You want to select the last line in each group. You can do this with the window function called row_number() (assuming you are using SQL Server 2005 or greater):

Select v.*
from (select v.*,
             ROW_NUMBER() over (partition by c015, c003, c074 order by mesoyear desc) as seqnum
      from CWLDATEN_91.dbo.v021
     ) v
where seqnum = 1;

Row_number() assigns a sequential number to rows in a group. So, all rows with the same value for c015, c003, and c074 (based on the partition by clause) are in a group and are numbered. The orders is by the most recent mesoyear first (based on the order by clause). So, the value of 1 in seqnum is the most recent year.

OTHER TIPS

You can solve this with ROW_NUMBER() assuming SQL Server 2005 or later

SELECT *
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY c015, c003, c074 ORDER BY mesoyear DESC) RowRank
      FROM CWLDATEN_91.dbo.v021)sub
WHERE RowRank = 1

The ROW_NUMBER() function just numbers rows in whatever fashion you dictate, here it's a grouped by your key fields, and ordered by mesoyear.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top