Je pense que les éléments suivants devraient travailler dans à peu près tous les produits SQL:
SELECT
cGift.gidnumb,
cGift.id,
cGift.date,
first.isfirst
FROM cGift
LEFT JOIN (
SELECT id, MIN(date) AS date, 't' AS isfirst
FROM cGift
GROUP BY id
) first ON cGift.id = first.id AND cGift.date = first.date
MISE À JOUR (portant sur des critères supplémentaires):
Si une personne peut donner plus d'une fois sur MIN(date)
et que vous voulez un don à marquer avec t
, vous pouvez, par exemple, faites ceci:
SELECT
cGift.gidnumb,
cGift.id,
cGift.date,
first.isfirst
FROM cGift
LEFT JOIN (
SELECT
MIN(g.gidnumb) AS g.gidnumb,
g.id,
g.date,
't' AS isfirst
FROM cGift g
INNER JOIN (
SELECT id, MIN(date) AS date
FROM cGift
GROUP BY id
) f ON g.id = f.id AND g.date = f.date
GROUP BY g.id, g.date
) first ON cGift.id = first.id AND cGift.date = first.date
C'est, la requête la plus interne trouve jours minimum pour chaque personne, comme dans la solution précédente, mais il détaille également la liste avec des valeurs spécifiques gidnumb
, en s'assurant que seulement une ligne par personne correspondra à cette liste dans la table cGift
.
Cette requête doit toujours pouvoir être exécutée dans n'importe quel SGBD. Il pourrait bien être moins efficace, étant donné le double groupement. Voici une alternative qui utilise uniquement SQL standard, pas de fonctionnalités spécifiques au fournisseur (il devrait aussi être un peu plus flexible que la requête précédente) aussi:
SELECT
gidnumb,
id,
date,
CASE
WHEN NOT EXISTS (
SELECT *
FROM cGift
WHERE id = g.id
AND (
date < g.date OR
date = g.date AND gidnumb < g.gidnumb
)
)
THEN 't'
END AS isfirst
FROM cGift g
Comme vous pouvez le voir, on calcule la colonne isfirst
à l'aide d'un auto-test sur la table: s'il n'y a pas de ligne dans ce tableau avec la même id
et soit la date antérieure ou, si la date est la même, moins gidnumb
, cette ligne doit être marquée comme t
.En l'absence de ELSE
une partie des CASE
, ELSE NULL
est implicite. Vous pouvez, si vous aimez ajouter quelque chose comme ELSE 'f'
. Cependant, votre produit SQL peut posséder des fonctionnalités dont vous pourriez bénéficier en construisant une requête peut-être plus simple et plus efficace. Certains produits, par exemple, prennent en charge les fonctions de classement (qui font partie de la norme SQL trop déjà, il est juste qu'ils ne sont pas encore universellement pris en charge), et voici ce que vous pourriez faire avec une fonction de classement appelé ROW_NUMBER()
:
SELECT
gidnumb,
id,
date,
CASE ROW_NUMBER() OVER (PARTITION BY id ORDER BY date, gidnumb)
WHEN 1
THEN 't'
END AS isfirst
FROM cGift g
Cette requête classe les lignes en les partitionnant par id
et en triant d'abord par date
, puis par gidnumb
. Chaque ligne avec le classement de 1
dans ce cas devient celui qui devrait être distingué avec t
.
merci, cela a fonctionné parfaitement – slicedtoad
OK, une chose a mal tourné. Apparemment, certaines personnes ont donné deux fois ou plus le même jour, ce qui a eu pour résultat que les gens ont plusieurs personnes. Puis-je utiliser gidnumb (toujours unique) comme deuxième critère pour min()? J'ai essayé mais j'ai des problèmes avec le groupage et la jointure. note: je ne peux pas utiliser 'min (gidnumb)' au lieu de 'min (date)' car gidnumb n'est pas toujours dans l'ordre des dates. – slicedtoad
@slicedtoad: S'il vous plaît voir ma mise à jour. –