我有一张手提箱正在进入或正在进入名为[Tote]的车站,如下所示:
Id Barcode Checksum PackageType Sts Destination LastStationExit LastUpdated
----------- ------------------ ----------- ----------- ----------- ----------- --------------- -----------------------
-2147483645 777000000000000001 586965230 0 1 NULL MS32 2016-04-19 14:15:32.577
-2147483644 777000000000000002 821846254 0 1 MS01 NULL 2016-04-19 15:08:16.140
-2147483643 777000000000000003 1174167790 0 1 NULL MS02 2016-04-19 15:08:20.340
-2147483642 777000000000000004 1543266542 0 1 NULL MS31 2016-04-19 15:08:24.510
-2147483641 777000000000000005 3424831 0 1 NULL MS01 2016-04-19 15:08:31.060
-2147483640 777000000000000006 573850175 0 1 MS01 NULL 2016-04-19 15:08:34.200
我有另一张桌子,其中包含所有名为[MezzanineStation]的现有电台:
Name
----
MS01
MS02
MS11
MS12
MS21
MS22
MS31
MS32
我正在尝试为每个电台计算到达的电量(目的地= StationName)以及电台有多少电量(LastStationExit = StationName)。
我写了以下请求,它正常工作:
-- Création d'une variable tampon pour isoler les bacs concernés par le calcul
DECLARE @FilteredToteExtract TABLE
(
Destination Varchar(4),
LastStationExit Varchar(4)
)
INSERT INTO @FilteredToteExtract([Destination],[LastStationExit])
SELECT [Destination],[LastStationExit]
FROM [Tote] T
WHERE [PackageType]=0
AND LastUpdated>=DATEADD(HOUR,-12,GETDATE())
AND EXISTS (SELECT * FROM [MezzanineStation] MS WHERE MS.[Name]=T.[Destination] OR MS.[Name]=T.[LastStationExit])
-- Calcul de l'occupation (prévue et courante) des gares de la mezzanine
SELECT DISTINCT MS.Name,T_Destination.[Count] AS NbTotesOngoing,T_LastStationExit.[Count] AS NbTotesInside
FROM [MezzanineStation] MS
LEFT JOIN
( SELECT
Destination,
COUNT(*) AS [Count]
FROM @FilteredToteExtract
GROUP BY Destination
) T_Destination
ON MS.Name = T_Destination.Destination
LEFT JOIN
( SELECT
LastStationExit,
COUNT(*) AS [Count]
FROM @FilteredToteExtract
GROUP BY LastStationExit
) T_LastStationExit
ON MS.Name = T_LastStationExit.LastStationExit
它给了我这样的结果:
Name NbTotesOngoing NbTotesInside
---- -------------- -------------
MS01 2 1
MS02 NULL 1
MS11 NULL NULL
MS12 NULL NULL
MS21 NULL NULL
MS22 NULL NULL
MS31 NULL 1
MS32 NULL NULL
以下是我在[Tote]表上创建的索引:
CREATE INDEX IX_Tote_PackageType ON [Tote]([PackageType])
CREATE INDEX IX_Tote_LastStationExit ON [Tote]([LastStationExit])
CREATE INDEX IX_Tote_LastUpdated ON [Tote]([LastUpdated])
您认为此请求可以更优化吗?
答案 0 :(得分:0)
您可以尝试(如果您还没有)替换您的" DISTINCT"使用" GROUP BY"。有时,这会产生积极的影响,因为将使用可能影响性能的不同执行计划。
如果您需要提高性能并根据您的要求,您可能希望使用内存优化表变量而不是普通表变量:https://msdn.microsoft.com/en-us/library/dn535766.aspx
答案 1 :(得分:0)
除非您在MezzanineStation中有重复项,否则您不应该需要明确的
如果你要实现,那么使用带有索引的#temp(不是表格)
但我认为你不需要实现
LastUpdated上的索引可能会有所帮助
SELECT MSM.[Name], TD.Count as TDcount, TL.Count as TLcount
FROM [MezzanineStation] MSM
LEFT JOIN ( SELECT MS.[Name], count(T.[Destination]) as [Count]
FROM [Tote] T
JOIN [MezzanineStation] MS
ON MS.[Name] = T.[Destination]
WHERE T.[PackageType] = 0
AND T.LastUpdated >= DATEADD(HOUR,-12,GETDATE())
GROUP BY MS.[Name]
) as TD
ON TD.[Name] = MSM.[Name]
LEFT join ( SELECT MS.[Name], count(T.[LastStationExit]) as count
FROM [Tote] T
JOIN [MezzanineStation] MS
ON MS.[Name] = T.[LastStationExit])
WHERE T.[PackageType] = 0
AND T.LastUpdated >= DATEADD(HOUR,-12,GETDATE())
GROUP BY MS.[Name]
) as TL
ON TL.[Name] = MSM.[Name]
如果其中一列始终为null,那么它很简单
SELECT MS.[Name]
, count(T.[Destination]) as [DestinationCount]
, count(T.[LastStationExit]) as [LastStationExitCount]
FROM [MezzanineStation] MS
LEFT JOIN [Tote] T
ON MS.[Name] = isnull(T.[Destination], T.[LastStationExit])
WHERE T.[PackageType] = 0
AND T.LastUpdated >= DATEADD(HOUR,-12,GETDATE())
GROUP BY MS.[Name]
答案 2 :(得分:-1)
所以,最后一个版本工作正常,完全符合KISS要求^ _ ^(感谢Paparazzi!)
CREATE FUNCTION dbo.GetMezzanineStationOccupancyForTotes()
RETURNS @StationOccupancy TABLE
(
[Level] Int NOT NULL, -- Niveau de la gare
[Priority] Int NOT NULL, -- Ordre de priorité spécifié dans la supervision (0 = Priorité la + élevée)
[Name] T_MEZZANINE_STATION_NAME NOT NULL, -- Nom de la gare
[Open] Bit NOT NULL, -- Ouverture/Fermeture de la gare (TRUE = Gare ouverte)
[NbTotesOngoing] Int, -- Nombre de bacs à destination de la gare
[NbTotesInside] Int, -- Nombre de bacs présents dans la gare
[StationOccupancy] AS [NbTotesOngoing]+[NbTotesInside] -- Occupation de la gare
)
AS
BEGIN
/* Constantes */
--<CST=ENU_TOTES_PACKAGE_TYPE>
-- Equivalent de l'énumération ENU_TOTES_PACKAGE_TYPE
DECLARE @TOTES_PACKAGE_TYPE_TOTE Int = 0, -- Bac
@TOTES_PACKAGE_TYPE_RETURN_BOX Int = 1, -- Carton retour
@MX_TOTES_PACKAGE_TYPE Int = 2
--</CST=ENU_TOTES_PACKAGE_TYPE>
/* Variables locales */
DECLARE @OldestIdleTime DateTime -- Date de dernière mise à jour la plus ancienne à prendre en compte
SELECT @OldestIdleTime=DATEADD(HOUR,-[NbHoursForgetTote],GETDATE())
FROM [Parameter] (NOLOCK)
-- Création d'une variable tampon pour isoler les bacs concernés par le calcul
DECLARE @FilteredToteExtract TABLE
(
Destination Varchar(4),
LastStationExit Varchar(4)
)
INSERT INTO @FilteredToteExtract([Destination],[LastStationExit])
SELECT [Destination],[LastStationExit]
FROM [Tote] T (NOLOCK)
WHERE [PackageType]=@TOTES_PACKAGE_TYPE_TOTE
AND LastUpdated>=@OldestIdleTime
AND EXISTS (SELECT * FROM [MezzanineStation] MS WHERE MS.[Name]=T.[Destination] OR MS.[Name]=T.[LastStationExit])
/* Fonction */
-- Calcul de l'occupation (prévue et courante) des gares de la mezzanine
INSERT INTO @StationOccupancy
SELECT
MS.[Level],
MS.[Priority],
MS.[Name],
MS.[Open],
ISNULL(COUNT(T.[Destination]),0),
ISNULL(COUNT(T.[LastStationExit]),0)
FROM [MezzanineStation] MS (NOLOCK)
LEFT JOIN @FilteredToteExtract T
ON MS.[Name] = ISNULL(T.[Destination],T.[LastStationExit])
GROUP BY MS.[Name],MS.[Level],MS.[Priority],MS.[Open]
/* Résultats */
RETURN
END