2016-04-19 43 views
-1

我有手提包打算或正在进入一个名为[手提包]站的表,这样的条件:SQL:传播COUNT()在多列

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 

我试图来算,每一个站,许多手提包如何去(目的地=工作站名称)以及有多少货箱进入车站(LastStationExit =工作站名称)。

我写了下面的请求,其正常工作:

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

这里是我的[手提包]表中创建的索引:

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

您认为这个请求可以更优化吗?

回答

-1

所以,工作正常,完全的最后修订符合KISS要求^ _ ^(感谢狗仔队!)

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

为什么我是否被降低了?我认为给出正确和整洁的答案会很好。 –

0

你可以尝试(如果你还没有做)用“GROUP BY”代替你的“DISTINCT”。有时候,这可能会产生积极的效果,因为将使用不同的执行计划,这可能会影响性能。

如果您需要提高性能,并根据您的要求,您可能需要使用一个内存优化表变量,而不是一个正常的表变量:https://msdn.microsoft.com/en-us/library/dn535766.aspx

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] 

如果列一个总是空那么很简单

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

我删除了DISTINCT因为在[MezzanineStation]中确实没有重复。 –

+0

实际上,对于每条记录,其中一列应始终为空,因为手提包不能同时“进入”和“进入”电台......起初,我是这样设计的,以处理奇怪的情况,他们是空的,但你说得对,我会像你说的那样简化它。 –

+0

已有[LastUpdated]^_ ^的索引对于另一位客户,我尝试通过触发器更新这种列,但在性能方面表现令人难以置信,因此现在只需更新其他数据... –