J'ai une table où je stocke des données de durée. la table a un schéma similaire à:
ID INT NOT NULL IDENTITY(1,1)
RecordID INT NOT NULL
StartDate DATE NOT NULL
EndDate DATE NULL
Et j'essaie de déterminer les dates de début et de fin de chaque identifiant d'enregistrement, donc les dates minimales StartDate et EndDate maximales. StartDate n'est pas nullable, donc je n'ai pas à m'inquiéter à ce sujet, mais j'ai besoin de MAX (EndDate) pour indiquer qu'il s'agit actuellement d'une durée d'exécution.
Il est important que je maintienne la valeur NULL de EndDate et que je la traite comme la valeur maximale.
La tentative la plus simple (ci-dessous) ne fonctionne pas, soulignant le problème selon lequel MIN et MAX ignoreront NULLS (source: http://technet.Microsoft.com/en-us/library/ms179916.aspx ).
SELECT recordid, MIN(startdate), MAX(enddate) FROM tmp GROUP BY recordid
J'ai créé un SQL Fiddle avec la configuration de base terminée.
http://sqlfiddle.com/#!3/b0a75
Comment puis-je plier SQL Server 2008 à ma volonté pour produire le résultat suivant à partir des données fournies dans SQLFiddle?
RecordId Start End
1 2009-06-19 NULL
2 2012-05-06 NULL
3 2013-01-25 NULL
4 2004-05-06 2009-12-01
C'est un peu moche mais parce que les NULL
s ont une signification particulière pour vous, c'est la façon la plus propre de le faire:
SELECT recordid, MIN(startdate),
CASE WHEN MAX(CASE WHEN enddate IS NULL THEN 1 ELSE 0 END) = 0
THEN MAX(enddate)
END
FROM tmp GROUP BY recordid
C'est-à-dire que si une ligne a un NULL
, nous voulons le forcer à être la réponse. Nous ne devons renvoyer le NULL
(ou MIN
) que si aucune ligne ne contient un MAX
.
L’effet souhaité est de traiter la valeur NULL comme la date la plus longue possible, puis de la remplacer par NULL à la fin:
SELECT RecordId, MIN(StartDate), NULLIF(MAX(COALESCE(EndDate,'9999-12-31')),'9999-12-31')
FROM tmp GROUP BY RecordId
Selon votre violon, cela retournera les résultats exacts que vous spécifiez dans toutes les conditions.
in my expression - count (enddate) compte le nombre de lignes dont la date de fin n'est pas nulle. count (*) compte le nombre de lignes total. En comparant, vous pouvez facilement déterminer si une date de fin contient null. Si elles sont identiques, alors max (enddate) est le résultat. Sinon, le cas par défaut retournera null qui est aussi la réponse. C'est un moyen très populaire de faire cette vérification exacte.
SELECT recordid,
MIN(startdate),
case when count(enddate) = count(*) then max(enddate) end
FROM tmp
GROUP BY recordid
Utilisez IsNull
SELECT recordid, MIN(startdate), MAX(IsNull(enddate, Getdate()))
FROM tmp
GROUP BY recordid
J'ai modifié MIN dans la deuxième instruction en MAX
En supposant que vous n'ayez qu'un seul enregistrement avec null dans la colonne EndDate pour un RecordID donné, quelque chose comme ceci devrait vous donner le résultat souhaité:
WITH cte1 AS
(
SELECT recordid, MIN(startdate) as min_start , MAX(enddate) as max_end
FROM tmp
GROUP BY recordid
)
SELECT a.recordid, a.min_start ,
CASE
WHEN b.recordid IS NULL THEN a.max_end
END as max_end
FROM cte1 a
LEFT JOIN tmp b ON (b.recordid = a.recordid AND b.enddate IS NULL)
Utilisez la fonction analytique:
select case when
max(field) keep (dense_rank first order by datfin desc nulls first) is null then 1
else 0 end as flag
from MYTABLE;