基于日期比较的SQL计数

时间:2018-04-05 21:55:43

标签: sql sql-server

我已经获得了以下SQL查询,该查询为我提供了所有超过两年的资产,按组织细分。然后我必须再次运行它,只需删除WHERE子句中的日期比较部分,找出我的资产总数,这样我就可以给出一个旧的计数,一个总数,然后一个%

有没有办法将所有这些作为单个查询执行?我在查询中可能会考虑某种类型的case语句吗?

SELECT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, COUNT(DISTINCT a.LabAssetSerialNbr) TotalAssets
FROM vw_DimLabAsset a
INNER JOIN vw_DimWorker w ON w.WorkerKey = a.LabAssetAssignedToWorkerKey
INNER JOIN vw_DimOrganizationHierarchy o ON o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
    AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
WHERE a.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0)
    AND a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
    AND a.LabAssetHardwareStatus <> 'retired'
    AND (a.LabAssetHardwareSubStatus IS NULL OR a.LabAssetHardwareSubStatus <> 'archive')
GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm
ORDER BY 1, 2

我尝试将其添加到选择:`

SUM(CASE WHEN a.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END)

但是,它不会返回与TotalAssets值相同的计数。

更新

这是我最终的最终查询:

DECLARE @date DateTime
SELECT @date = DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0);

WITH pphw AS 
(
    SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr, MIN(a.SystemCreatedOnDtm) MinCreated
    FROM vw_DimLabAsset a
    INNER JOIN vw_DimWorker w ON a.LabAssetAssignedToWorkerKey = w.WorkerKey
    INNER JOIN vw_DimOrganizationHierarchy o ON w.WorkerOrganizationUnitCd = o.OrganizationHierarchyUnitCd
        AND o.OrganizationHierarchyUnitLevelThreeNm IS NOT NULL
        AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
    WHERE LabAssetHardwareStatus <> 'Retired'
        AND (LabAssetHardwareSubStatus IS NULL OR LabAssetHardwareSubStatus <> 'Archive')
        AND a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
    GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
)
SELECT OrganizationHierarchyUnitLevelThreeNm, OrganizationHierarchyUnitLevelFourNm, 
    SUM(CASE WHEN MinCreated < @date THEN 1 ELSE 0 END) AssetsOverTwoYears,
    COUNT(DISTINCT LabAssetSerialNbr) TotalAssets
FROM pphw
GROUP BY OrganizationHierarchyUnitLevelThreeNm, OrganizationHierarchyUnitLevelFourNm
HAVING SUM(CASE WHEN MinCreated < @date THEN 1 ELSE 0 END) > 0
ORDER BY 1, 2

2 个答案:

答案 0 :(得分:1)

我的回答类似于tysonwright,但我认为GROUP BY子句应该在子选择之外。但是,我希望样本数据能够验证这一点。最重要的是,您应首先通过子选择收集您想要计算指标的所有记录。从那里,您可以执行SUMs和COUNTs。

SELECT TMP1.OrganizationHierarchyUnitLevelThreeNm
    ,TMP1.OrganizationHierarchyUnitLevelFourNm
    ,TotalAssets = COUNT(TMP1.LabAssetSerialNbr)
    ,AssetsOver2YearsOld = SUM(TMP1.AssetOver2YearsOldInd)
    ,PercAssetsOver2YearsOld = SUM(TMP1.AssetOver2YearsOldInd) / COUNT(TMP1.LabAssetSerialNbr)
FROM (SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
            ,AssetOver2YearsOldInd = CASE WHEN a.SystemCreatedOnDtm < DATEADD(d, DATEDIFF(d, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END
        FROM vw_DimLabAsset a
        INNER JOIN vw_DimWorker w 
            ON w.WorkerKey = a.LabAssetAssignedToWorkerKey
        INNER JOIN vw_DimOrganizationHierarchy o 
            ON o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
            AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
        WHERE a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
            AND a.LabAssetHardwareStatus <> 'retired'
            AND (a.LabAssetHardwareSubStatus IS NULL 
                    OR a.LabAssetHardwareSubStatus <> 'archive')
        ) TMP1
GROUP BY TMP1.OrganizationHierarchyUnitLevelThreeNm, TMP1.OrganizationHierarchyUnitLevelFourNm
ORDER BY 1, 2

<强>更新

要按日期时间删除重复项,您可以使用MIN或MAX功能,具体取决于您的要求:

SELECT TMP1.OrganizationHierarchyUnitLevelThreeNm
    ,TMP1.OrganizationHierarchyUnitLevelFourNm
    ,TotalAssets = COUNT(TMP1.LabAssetSerialNbr)
    ,AssetsOver2YearsOld = SUM(CASE WHEN TMP1.MaxSystemCreatedOnDtm < DATEADD(d, DATEDIFF(d, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END)
    ,PercAssetsOver2YearsOld = SUM(CASE WHEN TMP1.MaxSystemCreatedOnDtm < DATEADD(d, DATEDIFF(d, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END) / COUNT(TMP1.LabAssetSerialNbr)
FROM (SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr, MaxSystemCreatedOnDtm = MAX(a.SystemCreatedOnDtm)
        FROM vw_DimLabAsset a
        INNER JOIN vw_DimWorker w 
            ON w.WorkerKey = a.LabAssetAssignedToWorkerKey
        INNER JOIN vw_DimOrganizationHierarchy o 
            ON o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
            AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
        WHERE a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
            AND a.LabAssetHardwareStatus <> 'retired'
            AND (a.LabAssetHardwareSubStatus IS NULL 
                    OR a.LabAssetHardwareSubStatus <> 'archive')
        GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
        ) TMP1
GROUP BY TMP1.OrganizationHierarchyUnitLevelThreeNm, TMP1.OrganizationHierarchyUnitLevelFourNm
ORDER BY 1, 2

答案 1 :(得分:0)

我认为这可以满足您的需求:

SELECT 
    s.OrganizationHierarchyUnitLevelThreeNm, 
    s.OrganizationHierarchyUnitLevelFourNm, 
    COUNT(*) TotalAssets,
    SUM(CASE    WHEN s.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0)
                THEN 1 ELSE 0 END) AssetsOver2YearsOld,
    SUM(CASE    WHEN s.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0)
                THEN 1 ELSE 0 END) / COUNT(*) PercAssetsOver2YearsOld
FROM 
    (   
    SELECT
        o.OrganizationHierarchyUnitLevelThreeNm, 
        o.OrganizationHierarchyUnitLevelFourNm
        a.LabAssetSerialNbr,
        a.SystemCreatedOnDtm
    FROM    
        vw_DimLabAsset a
    INNER JOIN 
        vw_DimWorker w 
    ON 
        w.WorkerKey = a.LabAssetAssignedToWorkerKey
    INNER JOIN 
        vw_DimOrganizationHierarchy o 
    ON 
        o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
    AND 
        o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
    WHERE 
        a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
    AND 
        a.LabAssetHardwareStatus <> 'retired'
    AND 
        (a.LabAssetHardwareSubStatus IS NULL OR a.LabAssetHardwareSubStatus <> 'archive')
    GROUP BY 
        o.OrganizationHierarchyUnitLevelThreeNm, 
        o.OrganizationHierarchyUnitLevelFourNm
        a.LabAssetSerialNbr,
        a.SystemCreatedOnDtm
    ) AS s