2016-04-19 7 views
-1

ich eine Tabelle von totes haben gehen oder sein in benannte Stationen [Tote], wie folgt aus:SQL: Spread Count() durch die Bedingungen in mehreren Spalten

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 

ich einen anderen Tisch haben, die enthält alle bestehende Station namens [MezzanineStation]:

Name 
---- 
MS01 
MS02 
MS11 
MS12 
MS21 
MS22 
MS31 
MS32 

ich für jede Station zu zählen bin versucht, wie viele Behälter zu (Ziel = Station) gehen und wie viele Behälter sind in die Station (LastStationExit = Station).

Ich schrieb die folgende Anfrage, die korrekt funktioniert:

-- 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 

Es gibt mir diese Art von Ergebnis:

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 

sind hier der Index, den ich auf dem [Tote] Tabelle erstellt:

CREATE INDEX IX_Tote_PackageType ON [Tote]([PackageType]) 
CREATE INDEX IX_Tote_LastStationExit ON [Tote]([LastStationExit]) 
CREATE INDEX IX_Tote_LastUpdated ON [Tote]([LastUpdated]) 

Glauben Sie, dass diese Anfrage optimiert werden kann?

Antwort

-1

die letzte Revision Also, der gut arbeitet und vollständig die KISS Anforderungen^_^(dank 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][email protected]_PACKAGE_TYPE_TOTE 
     AND LastUpdated>[email protected] 
     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 
trifft
+0

Warum wurde ich abgelehnt? Ich dachte, die richtige und ordentliche Antwort zu geben wäre etwas Nettes. –

0

Sie können versuchen (wenn Sie noch nicht getan haben), um Ihre „distinct“ unter Verwendung von „GROUP BY“ zu ersetzen. Dies kann sich manchmal positiv auswirken, da verschiedene Ausführungspläne verwendet werden, die sich auf die Leistung auswirken können.

Wenn Sie die Performance verbessern müssen und je nach Ihren Anforderungen, könnte man statt einer normalen Tabellenvariable eine speicheroptimierte Tabellenvariable verwenden möchten: https://msdn.microsoft.com/en-us/library/dn535766.aspx

0

Sie sollten nicht den eindeutigen müssen, wenn Sie Duplikate in MezzanineStation
wenn Sie dann eine #temp mit Indizes (keine Tabelle)
aber ich glaube nicht, dass Sie
ein Index für Lastupdated wahrscheinlich

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] 
helfen würde materialisieren müssen materialisieren verwenden werden

, wenn einer der Spalte immer null ist, dann ist es einfach

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] 
+0

Ich habe die DISTINCT entfernt, weil es in [MezzanineStation] keine Duplikate gibt. –

+0

Na ja, eigentlich eine der Spalte sollte immer für jeden Datensatz null sein, weil eine tote nicht beide „gehen“ werden kann und „in“ einer Station ... Zuerst entwarf ich es auf diese Weise seltsame Situationen zu behandeln, in denen keiner der Sie sind null, aber du hast recht, ich werde es vereinfachen, wie du gesagt hast. –

+0

Es gab bereits ein Index für [Lastupdated]^_^Für einen anderen Kunden habe ich versucht, über einen Auslöser dieser Art von Spalte zu aktualisieren, aber es ist unglaublich schlecht in Bezug auf die Leistung so dass ich jetzt aktualisieren es einfach mit den anderen Daten ... –