Groupe SQL par date, mais obtenez aussi des dates sans enregistrement
Question
Existe-t-il un moyen simple de créer un GROUP BY DATE (horodatage)
incluant tous les jours d'une période, qu'il y ait ou non des enregistrements associés à cette date?
En principe, je dois générer un rapport comme celui-ci:
24 Dec - 0 orders
23 Dec - 10 orders
22 Dec - 8 orders
21 Dec - 2 orders
20 Dec - 0 orders
La solution
Au lieu d'utiliser GROUP BY, créez une table (peut-être une table temporaire) contenant les dates spécifiques que vous souhaitez, par exemple:
24 Dec
23 Dec
22 Dec
21 Dec
20 Dec
Ensuite, joignez cette table à la table Orders.
Autres conseils
En supposant que vous ayez plus d’ordres que de dates, cela pourrait fonctionner:
select date, count(id) as orders
from
(
SELECT DATE_ADD('2008-01-01', INTERVAL @rn:=@rn+1 DAY) as date from (select @rn:=-1)t, `order` limit 365
) d left outer join `order` using (date)
group by date
Une méthode consiste à créer une table de calendrier et à la rejoindre.
Je le créerais de manière permanente, puis créerais une tâche qui insèrerait de nouvelles dates. Cela pourrait être fait chaque semaine, chaque jour, tous les mois, etc.
Notez que je suppose que vous convertissez votre horodatage en date.
vous devez générer un jeu de résultats intermédiaire avec toutes les dates que vous souhaitez inclure dans le résultat ...
si vous faites cela dans un proc stocké, vous pouvez créer une table temporaire ou une variable de table (je ne connais pas les capacités de MySQL), mais une fois que vous avez toutes les dates dans une table ou un ensemble de résultats
Joignez simplement les données réelles de la table temporaire, en utilisant une jointure externe
Dans SQL Server, ce serait comme ceci
Declare @Dates Table (aDate DateTime Not Null)
Declare @StartDt DateTime Set @StartDt = 'Dec 1 2008'
Declare @EndDt DateTime Set @EndDt = 'Dec 31 2008'
While @StartDt < @EndDt Begin
Insert @Dates(aDate) Values(@StartDt)
Set @StartDt = DateAdd(Day, 1, @StartDt)
End
Select D.aDate, Count(O.*) Orders
From @Dates D Left Join
OrderTable O On O.OrderDate = D.aDate
Group By D.aDate
Dans un entrepôt de données, la méthode utilisée consiste à créer une table contenant toutes les dates et à créer une clé étrangère entre vos données et la table de dates. Je ne dis pas que c'est la meilleure façon de procéder dans votre cas, mais bien que c'est la meilleure pratique dans les cas où de grandes quantités de données doivent être cumulées de nombreuses manières pour les besoins de la création de rapports.
Si vous utilisez une couche de génération de rapports sur SQL Server, vous pouvez simplement écrire une logique pour insérer les dates manquantes dans la plage d'intérêt après le retour des données et avant le rendu de votre rapport.
Si vous créez vos rapports directement à partir de SQL Server et que vous ne disposez pas déjà d'un entrepôt de données et que vous n'avez pas le temps ou besoin de le créer pour l'instant, je créerais un tableau de dates et le joindrais. Le formatage nécessaire pour faire la jointure et obtenir le résultat souhaité peut sembler un peu louche, mais le travail sera fait.
Il existe un moyen assez simple de faire cela & # 8230; sauf que je ne m'en souviens pas. Mais j’ai adapté cette requête de ce fil :
SELECT
DISTINCT(LEFT(date_field,11)) AS `Date`,
COUNT(LEFT(date_field,11)) AS `Number of events`
FROM events_table
GROUP BY `Date`
Cela fonctionne aussi dans MySQL