web-dev-qa-db-fra.com

Comment utiliser "Partition By" ou "Max"?

J'ai le tableau suivant (my_data):

year |  X  |  Y
-----+-----+-----
2010 |  A  |  10
2011 |  A  |  20
2011 |  B  |  99
2009 |  C  |  30
2010 |  C  |  40


quelle est la meilleure/la plus petite des instructions SQL pour récupérer uniquement les données relatives à l'année la plus élevée et regroupées par 'X', comme ceci:

year |  X  |  Y
-----+-----+-----
2011 |  A  |  20
2011 |  B  |  99
2010 |  C  |  40


Notez que cette table de résultats sera utilisée dans une jointure.

20
Stef Heyenrath
select year, x,y
from (
      select year, x, y, max(year) over(partition by x) max_year
      from my data
      )
where  year = max_year
24
schurik
select * from (
  select year, x, y, row_number() over (partition by x order by year desc ) rn 
  from my_data
) where rn = 1
12
Frank Schmitt

C'est beaucoup plus simple que les autres solutions:

SELECT x, max(year), MAX(y) KEEP (DENSE_RANK FIRST ORDER BY year DESC)
  FROM table
  GROUP BY x
3
Gary Myers

Vous pouvez également être portable et utiliser un OUTER JOIN:

select t1.year, t1.x, t1.y
  from my_data t1
  left join my_data t2
    on t2.x = t1.x
   and t2.year > t1.year
 where t2.x is null
3
Benoit

Gary Myers, votre solution ne fonctionne pas si, par exemple, pour la valeur A, l'année est plus petite que 2010 et cette année a une valeur maximale. (Par exemple, si la ligne 2005, A, 50 existait) Pour obtenir la solution correcte, utilisez ce qui suit. (qui échange juste les valeurs)

SELECT x, max(y), MAX(year) KEEP (DENSE_RANK FIRST ORDER BY y DESC)
FROM test
GROUP BY x
1
AleksandarT

Vous pouvez utiliser une expression de table commune (CTE), fonctionne également avec les lignes dupliquées (si nécessaire) Le plan d'exécution est identique, plus ou moins

;With my_data_cte as (
    SELECT [year], x,y,ROW_NUMBER() OVER (
        PARTITION BY x
        ORDER BY [year] desc) as rn
FROM [dbo].[my_data])
select [year], x,y from my_data_cte 
where rn = 1
1
Artyom
select year, x, y 
 from my_data stable 
where stable.year = (select max(year) 
                     from my_data tables 
                     where tables.x = stable.x);
0
minglotus
  -- I had a slightly different case and just wandering why this one should't work 
  SELECT my_data.x , my_data.y , my_data1.max_year 
  FROM my_data
  INNER JOIN 
  ( 
    SELECT x , max (year ) as max_year
    FROM my_data
    -- WHERE 1=1
    -- AND FILTER1=VALUE1
    GROUP BY my_data.x
  ) my_data1
  ON ( my_data.x = my_data1.x )
0
Yordan Georgiev