2010-07-20 12 views
0

Une table existe dans Microsoft SQL Server avec l'ID d'enregistrement, la date de début, la date de fin et la quantité. L'idée est que pour chaque enregistrement, la quantité/nombre total de jours dans la gamme = quantité journalière.Requête SQL pour la plage de dates, plusieurs heures de début et de fin

Étant donné qu'il existe une table contenant toutes les dates possibles, comment puis-je générer un jeu de résultats dans SQL Server pour ressembler à l'exemple suivant?

EX:

RecordID | Start Date | End Date | Quantity 
1  | 1/1/2010 | 1/5/2010 | 30000 
2  | 1/3/2010 | 1/9/2010 | 20000 
3  | 1/1/2010 | 1/7/2010 | 10000 

Results as 
1  | 1/1/2010 | QTY (I can do the math easy, just need the dates view) 
1  | 1/2/2010 | 
1  | 1/3/2010 | 
1  | 1/4/2010 | 
1  | 1/3/2010 | 
2  | 1/4/2010 | 
2  | 1/5/2010 | 
2  | 1/6/2010 | 
2  | 1/7/2010 | 
2  | 1/8/2010 | 
2  | 1/9/2010 | 
3  | 1/1/2010 | 
3  | 1/2/2010 | 
3  | 1/3/2010 | 
3  | 1/4/2010 | 
3  | 1/5/2010 | 
3  | 1/6/2010 | 
3  | 1/7/2010 | 

Regroupement des dates que je pourrais obtenir ensuite obtenir la somme de la quantité ce jour-là mais le dernier jeu de résultat ne peut pas être totale en raison des filtres fournis par l'utilisateur qui peuvent exclure certains de ces dossiers en bas de la route.

EDIT

Pour clarifier les choses, cela est juste un échantillon. Les filtres ne sont pas pertinents car je peux me joindre sur le côté pour tirer dans les détails liés à l'ID d'enregistrement dans les résultats.

Les données réelles contiennent N enregistrements qui augmente chaque semaine, les dates ne sont jamais les mêmes. Il pourrait y avoir 2000 enregistrements avec des dates de début et de fin différentes ... C'est ce que je veux générer une vue. Je peux rejoindre à droite les données pour faire le reste de ce dont j'ai besoin

Je devrais aussi mentionner que c'est pour les données passées, présentes et futures. J'aimerais me débarrasser d'une table temporaire de dates. J'utilisais une requête récursive pour obtenir toutes les dates qui existent dans une période de 50 ans mais cela dépasse les limites de MAXRECURSION pour une vue, que je ne peux pas utiliser.

+0

Je ne suis pas sûr que je comprends les informations sur les filtres fournis par l'utilisateur. Pouvez-vous donner plus de détails? – bobs

+0

Les filtres ne sont vraiment pas pertinents. Je vais rejoindre cette liste à la liste principale qui contient des informations sur les quantités, etc et peut utiliser ces faits pour dériver des valeurs à travers le tableau – Mohgeroth

Répondre

3

Réponse

select RecordId,d.[Date], Qty/ COUNT(*) OVER (PARTITION BY RecordId) AS Qty 
from EX join Dates d on d.Date between [Start Date] and [End Date] 
ORDER BY RecordId,[Date] 

NB: Les dessous de démonstration CTEs utiliser le date qui est le type de données SQL Server 2008 l'approche générale devrait fonctionner pour SQL2005 aussi bien que.

Test Case

/*CTEs for testing purposes only*/ 

WITH EX AS 
(
    SELECT 1 AS RecordId, 
    cast('1/1/2010' as date) as [Start Date], 
    cast('1/5/2010' as date) as [End Date], 
    30000 AS Qty 
union all 
    SELECT 2 AS RecordId, 
    cast('1/3/2010' as date) as [Start Date], 
    cast('1/9/2010' as date) as [End Date], 
    20000 AS Qty 
),Dates AS /*Dates Table now adjusted to do greater range*/ 
(

SELECT DATEADD(day,s1.number + 2048*s2.number,'1990-01-01') AS [Date] 
FROM master.dbo.spt_values s1 CROSS JOIN master.dbo.spt_values s2 
where s1.type='P' AND s2.type='P' and s2.number <= 8 
order by [Date] 
) 


select RecordId,d.[Date], Qty/ COUNT(*) OVER (PARTITION BY RecordId) AS Qty 
from EX join Dates d on d.Date between [Start Date] and [End Date] 
ORDER BY RecordId,[Date] 

Résultats

RecordId Date  Qty 
----------- ---------- ----------- 
1   2010-01-01 6000 
1   2010-01-02 6000 
1   2010-01-03 6000 
1   2010-01-04 6000 
1   2010-01-05 6000 
2   2010-01-03 2857 
2   2010-01-04 2857 
2   2010-01-05 2857 
2   2010-01-06 2857 
2   2010-01-07 2857 
2   2010-01-08 2857 
2   2010-01-09 2857 
+0

J'ai omis de mentionner ceci est pour des données passées, présentes et futures. J'adore l'idée que je n'ai pas besoin d'obtenir les dates d'une table temporaire, mais cela pourrait malheureusement aller de l'avant deux ans et l'utilisation de cette requête par rapport à ces résultats ne donne aucun résultat pour les données futures. J'aimerais cependant me débarrasser de cette table de dates temporaires ... – Mohgeroth

+0

@Mohgeroth - La table de dates dédiée avec un index à date sera la solution la plus efficace.Vous devriez être en mesure d'ajuster facilement ma requête pour regarder cela au lieu de ma table de dates de démonstration. –

+0

Que voulez-vous dire "futures dates"? Sa requête fonctionne très bien pour des périodes de plus de 22 ans, qu'elles soient passées ou futures. Si vous voulez dire que vous voulez voir les dates futures dans la liste avec la quantité 0 comme "2011-01-01 0", vous devrez alors inclure un paramètre spécifiant la plage totale des dates de début et de fin. – ErikE

1

Je pense que vous pouvez essayer ceci.

SELECT [Quantities].[RecordID], [Dates].[Date], SUM([Quantity]) 
FROM [Dates] 
JOIN [Quantities] on [Dates].[Date] between [Quantities].[Start Date] and [End Date] 
GROUP BY [Quantities].[RecordID], [Dates].[Date] 
ORDER BY [Quantities].[RecordID], [Dates].[Date] 
+0

Beautiful. Je n'ai pas pensé à utiliser entre dans ma jointure. J'ai toujours cette table temporaire des dates que je voudrais éliminer mais si cela ne peut pas être fait, ceci est une solution propre au problème – Mohgeroth

Questions connexes