I have a table of totes going or being into stations named [Tote], like this:
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
I've got another table which contains all the existing station named [MezzanineStation]:
Name
----
MS01
MS02
MS11
MS12
MS21
MS22
MS31
MS32
I'm trying to count, for every station, how many totes are going to (Destination=StationName) and how many totes are into the station (LastStationExit=StationName).
I wrote the following request which works correctly:
-- 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
It gives me this kind of result:
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
Here are the index that I created on the [Tote] table:
CREATE INDEX IX_Tote_PackageType ON [Tote]([PackageType])
CREATE INDEX IX_Tote_LastStationExit ON [Tote]([LastStationExit])
CREATE INDEX IX_Tote_LastUpdated ON [Tote]([LastUpdated])
Do you think this request can be more optimized?
So, the last revision which works fine and completely meets the KISS requirements ^_^ (thanks to 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