1
votes

SQL comment obtenir des lignes avec la valeur maximale d'une colonne dans la table en lignes groupées

J'ai une table avec des colonnes ('name', 'maj', 'min', 'patch') pour chaque nom il peut y avoir plusieurs versions majeures / mineures / patch. Pour chaque nom, j'ai besoin d'obtenir les valeurs majeures + mineures pour le «patch» maximum pour ce majeur / mineur.

par exemple table 'data'

SELECT id, name, maj, min, patch FROM data group by name, maj, min order by name, patch desc

Résultat attendu:

|id|name|maj|min|patch|
|3 |n1  |1  |0  | 3   |
|4 |n2  |1  |0  | 1   |
|6 |n2  |2  |0  | 2   |

J'ai seulement réussi à regrouper ces données par ces champs et ordonné mais je ne sais pas pour obtenir uniquement les lignes avec le patch maximum pour chaque majeur / mineur

|id|name|maj|min|patch|
|1 |n1  |1  |0  | 1   |
|2 |n1  |1  |0  | 2   |
|3 |n1  |1  |0  | 3   |
|4 |n2  |1  |0  | 1   |
|5 |n2  |2  |0  | 1   |
|6 |n2  |2  |0  | 2   |


1 commentaires

regardez dans la fonction MAX (), cela devrait vous aider ici


4 Réponses :


1
votes

La requête suivante se rapproche de ce que vous voulez:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY name, maj, `min` ORDER BY patch DESC) rn
    FROM data
)

SELECT id, name, maj, `min`, patch
FROM cte
WHERE rn = 1;

Mais cela n'inclut pas la colonne id , qui ne fait pas partie de la requête d'agrégation . Si vous voulez une approche générale pour inclure toutes les lignes correspondantes, envisagez d'utiliser ROW_NUMBER:

SELECT
    name,
    maj,
    `min`,
    MAX(patch) AS patch
FROM data
GROUP BY
    name,
    maj,
    `min`;


0 commentaires

-1
votes

Vous pouvez simplement utiliser Clause pour y parvenir Exemple simple

SELECT id, name, maj, min, max(patch) AS max_patch FROM data GROUP BY patch DESC HAVING MAX(patch) >1;

J'espère que cela vous aidera


1 commentaires

Non, simplement, vous ne pouvez pas le faire.



1
votes

Avec NOT EXISTS:

| id  | name | maj | min | patch |
| --- | ---- | --- | --- | ----- |
| 3   | n1   | 1   | 0   | 3     |
| 4   | n2   | 1   | 0   | 1     |
| 6   | n2   | 2   | 0   | 2     |

Voir le démo .
Résultats:

select t.* from tablename t
where not exists (
  select 1 from tablename
  where name = t.name and maj = t.maj and min = t.min and patch > t.patch
)  


1 commentaires

Merci d'avoir partagé le db-fiddle! super utile



1
votes

Vous pouvez également le faire avec une sous-requête corrélée:

selet t.*
from t
where t.patch = (select max(t2.patch)
                 from t t2
                 where t2.name = t.name and
                       t2.maj = t.maj and
                       t2.min = t.min
                );

Si vous avez une grande base de données, alors un index sur (name, maj, min, patch) code > fournira de bonnes performances.


1 commentaires

C'était le plus facile à comprendre pour moi. Merci!