1
votes

Comment sélectionner la première ligne pour chaque ensemble de lignes avec une valeur commune

À titre d'exemple, j'ai un tableau comme celui-ci:

SELECT * FROM ( 
    SELECT
    md.week_dt, 
    md.cust, 
    md.y_w, 
    md.y, 
    md.w, 
    md.y_fp, 
    FROM MASTER_DATES md
) t1
Where 
    t1.week_dt IN (
    SELECT TOP(1) t2.week_dt
    FROM MASTER_DATES t2
    WHERE t2.week_dt = t1.week_dt AND t2.cust = t1.cust
    ORDER BY t2.week_dt
)
ORDER BY t1.week_dt

La dernière colonne contient des informations sur l'année / la période fiscale. Je voudrais sélectionner une ligne pour chaque élément y_fp avec week_dt et y_w étant la première date pour cette année / période fiscale. Ainsi, choisir parmi les éléments ci-dessus donnerait:

week_dt     cust    y_w     w   y       y_fp
2011-01-29  ABC     201122  6   2011    201106
2011-02-19  ABC     201125  7   2011    201107
2011-03-19  ABC     201129  8   2011    201108
2011-04-16  ABC     201133  9   2011    201109

J'ai essayé de suivre cet exemple en utilisant TOP (1) au lieu de LIMIT mais j'ai le tableau entier me revint.

Voici ma requête:

week_dt     cust    y_w     w   y       y_fp
2011-01-29  ABC     201122  6   2011    201106
2011-02-05  ABC     201123  6   2011    201106
2011-02-12  ABC     201124  6   2011    201106
2011-02-19  ABC     201125  7   2011    201107
2011-02-26  ABC     201126  7   2011    201107
2011-03-05  ABC     201127  7   2011    201107
2011-03-12  ABC     201128  7   2011    201107
2011-03-19  ABC     201129  8   2011    201108
2011-03-26  ABC     201130  8   2011    201108
2011-04-02  ABC     201131  8   2011    201108
2011-04-09  ABC     201132  8   2011    201108
2011-04-16  ABC     201133  9   2011    201109
2011-04-23  ABC     201134  9   2011    201109

Notez que MASTER_DATES contient une clé primaire composite des colonnes week_dt et cust .


0 commentaires

3 Réponses :


1
votes

Essayez d'utiliser row_number et une partition by pour le diviser par md.y_fp

WITH C AS(
 SELECT
    md.week_dt, 
    md.cust, 
    md.y_w, 
    md.y, 
    md.w, 
    md.y_fp,
    row_number() over(partition by md.y_fp order by md.week_dt asc) as rn
FROM MASTER_DATES md
)
SELECT * 
FROM C 
WHERE RN = 1


0 commentaires

1
votes

Une méthode est row_number():

select md.*
from master_dates md
where md.week_date = (select min(md2.week_date)
                      from master_dates md2
                      where md2.cust = md.cust and md2.y_fp = md.y_fp
                     );

Dans certains cas, cependant, une sous-requête corrélée a de meilleures performances:

select md.*
from (select md.*,
             row_number() over (partition by md.cust, md.y_fp order by md.week_date desc) as seqnum
      from master_dates md
     ) md
where seqnum = 1;


0 commentaires

1
votes

Vos exemples de données et les résultats attendus indiquent qu'un simple groupement par est suffisant:

select
  min(week_dt) week_dt, 
  cust,
  min(y_w) y_w,
  w,
  y,
  y_fp
from MASTER_DATES 
group by cust, y, w, y_fp


2 commentaires

Désolé, la colonne y en double était un accident. Je vais éditer ça. Et oui, cela semble avoir fonctionné aussi et c'est très simple.


Vous avez besoin d'un regroupement et des valeurs minimales de 2 colonnes. C'est tout.