HI TousSQL Server 2008 Optimize FULL JOIN avec les déclarations de isNull
J'espérais que quelqu'un pourrait me aider à améliorer une requête que je dois exécuter périodiquement. Pour le moment, il faut plus de 40 minutes pour l'exécuter. Il utilise la totalité de la mémoire allouée pendant ce temps, mais l'utilisation du processeur est généralement de 2% à 5%, de temps en temps de 40% pendant quelques secondes.
Je possède ce tableau (exemple simplifié):
CREATE TABLE [dbo].[dataTable]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[dteEffectiveDate] [date] NULL,
[dtePrevious] [date] NULL,
[dteNext] [date] NULL,
[Age] [int] NULL,
[Count] [int] NULL
) ON [PRIMARY]
GO
Voici quelques valeurs d'entrée:
INSERT INTO [YourDB].[dbo].[dataTable]
([dteEffectiveDate]
,[dtePrevious]
,[dteNext]
,[Age]
,[Count])
VALUES
('2009-01-01',NULL,'2010-01-01',40,300),
('2010-01-01','2009-01-01', NULL,40,200),
('2009-01-01',NULL, '2010-01-01',20,100),
('2010-01-01','2009-01-01', NULL,20,50),
('2009-01-01',NULL,'2010-01-01',30,10)
GO
Chaque entrée a un champ dteEffectiveDate. De plus, chacun a un dtePrevious et dteNext, qui reflète les dates de la date d'entrée en vigueur précédente/suivante la plus proche. Maintenant, ce que je veux, c'est une requête qui va calculer la valeur moyenne sur les champs de comptage entre les périodes successives, dans un âge spécifique.
Ainsi, par exemple, dans les données ci-dessus, pour 40 ans, nous avons 300 à 200 et 2009/01/01 à 2010/01/01 de sorte que la requête doit produire 250.
Notez que 30 ans a seulement une entrée, 10. Ceci est à 2009/01/01. Il n'y a aucune entrée au 2010/01/01, mais nous savons que les données ont été saisies à ce moment-là, donc le fait qu'il n'y ait rien signifie que 30 est 0 à cette date. Par conséquent, la requête devrait produire 5.
Pour ce faire, j'utilise un FULL JOIN de la table sur lui-même, et utilise ISNULL pour sélectionner des valeurs. Voici mon code:
SELECT
ISNULL(T1.dteEffectiveDate,T2.dtePrevious) as [Start Date]
,ISNULL(T1.dteNext,T2.dteEffectiveDate) as [End Date]
,ISNULL(T1.Age,T2.Age) as Age
,ISNULL(T1.[Count],0) as [Count Start]
,ISNULL(T2.[Count],0) as [Count End]
,(ISNULL(T1.[Count],0)+ISNULL(T2.[Count],0))/2 as [Mid Count]
FROM
[ExpDBClient].[dbo].[dataTable] as T1
FULL JOIN [ExpDBClient].[dbo].[dataTable] as T2
ON
T2.dteEffectiveDate = T1.dteNext
AND T2.Age = T1.Age
WHERE ISNULL(T1.dteEffectiveDate,T2.dtePrevious) is not null
AND ISNULL(T1.dteNext,T2.dteEffectiveDate) is not null
GO
qui sort:
Start Date End Date Age Count Start Count End Mid Lives
2009-01-01 2010-01-01 40 300 200 250
2009-01-01 2010-01-01 20 100 50 75
2009-01-01 2010-01-01 30 10 0 5
Il fonctionne parfaitement, mais quand j'exécuter sur les données réelles, soit environ 7 m dossiers, il faut péniblement longue à exécuter.
Quelqu'un at-il des suggestions?
Merci
Karl
Quels index avez-vous sur la table? Y a-t-il un maximum de 2 lignes par âge? –
Aucun indice. Il n'y aura qu'une seule entrée par âge par dteEffectiveDate. Donc, selon le nombre de dates d'entrée en vigueur, il n'y a pas de limite au nombre de fois qu'un âge se présente. Mais il y aura toujours une seule combinaison de dteEffectiveDate, dtePrevious et dteNext pour chaque âge.(Ceci est simplifié, dans le vrai problème que je divise à travers beaucoup plus de champs) – Karl