Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Compte SQL pour inclure des valeurs nulles

Pas tellement la clause WHERE, mais le GROUP BY. La requête renverra uniquement des données pour les lignes qui existent. Cela signifie que lorsque vous regroupez par date d'horodatage, seuls les jours pour lesquels il existe des lignes seront renvoyés. SQL Server ne peut pas savoir à partir du contexte que vous voulez "remplir les blancs", et il ne saurait pas avec quoi.

La réponse normale est un CTE qui produit tous les jours que vous voulez voir, remplissant ainsi les blancs. Celui-ci est un peu délicat car il nécessite une instruction SQL récursive, mais c'est un truc bien connu :

WITH CTE_Dates AS
(
    SELECT @START AS cte_date
    UNION ALL
    SELECT DATEADD(DAY, 1, cte_date)
    FROM CTE_Dates
    WHERE DATEADD(DAY, 1, cte_date) <= @END
)
SELECT
cte_date as TIME_STAMP,
ISNULL(COUNT(HL_Logs.Time_Stamp), 0) AS counted_leads, 
FROM CTE_Dates
LEFT JOIN HL_Logs ON DATEADD(dd, 0, DATEDIFF(dd, 0, Time_Stamp)) = cte_date
WHERE Time_Stamp between @BEGIN and @END and ID_Location = @LOCATION
GROUP BY cte_date

En le décomposant, le CTE utilise une union qui fait référence à elle-même pour ajouter de manière récursive un jour à la fois à la date précédente et mémoriser cette date dans le cadre du tableau. Si vous exécutiez une instruction simple qui utilisait le CTE et que vous y sélectionniez simplement *, vous verriez une liste de dates entre le début et la fin. Ensuite, l'instruction joint cette liste de dates à la table de journal en fonction de la date d'horodatage du journal, tout en préservant les dates qui n'ont pas d'entrées de journal à l'aide de la jointure gauche (prend toutes les lignes du côté "gauche" si elles ont des lignes correspondantes sur le " côté droit ou non). Enfin, nous regroupons par date et comptons à la place et nous devrions obtenir la réponse que vous souhaitez.