【问题标题】:SQL That Will Exclude Certain Records将排除某些记录的 SQL
【发布时间】:2015-12-10 19:13:45
【问题描述】:

我正在为我们公司编写一份速度报告。这是从我们的车队收集的数据。我们已经配置了参数,以根据他们正在驾驶的状态、发布的该位置的速度限制等来标记超速超过某个阈值的人。

我的 SQL 查询正在使用 CTE。从我的 CTE 中选择时,我在其中包含两个选择语句。一种选择语句用于满足或超过阈值要求的记录。我有一个名为 SpeedingEvent 的字段,这些记录包含一个值“Y”表示是。第二个 select 语句返回不满足或超过阈值的记录,SpeedingEvent 值为“N”表示 No。这两个 select 语句的结果用 UNION 连接。

有点奇怪,但我的公司希望能够看到发生的超速事件,即使它们没有达到阈值。我的问题是,其中一些被排除的记录,即 SpeedingEvent 值为“N”的记录,在 SpeedingEvent =“Y”且日期和车队编号匹配的数据集中没有匹配记录。

因此,当我的 SSRS 报告生成时,我看到这些数据行被排除在外,但与满足阈值的现有记录没有任何关系。

我尝试创建一个子查询,但这不起作用,因为我收到一条错误消息,指出子查询返回的值超过 1 个,并且在使用某些比较值时不允许这样做。

这是我的代码示例。这不是全部,因为要返回许多字段。

WITH cteSpeedReport([List of fields])
AS
(
SELECT DISTINCT
     [List of fields]
FROM
     [4 views that are being joined]
WHERE
     [Criteria for meeting threshold]
)
SELECT DISTINCT
     [List of Fields]
FROM (
SELECT DISTINCT DStartDate, DEndDate, DAssetID, DFleet, (DMax - DStateLimit) as DMaxOver, DEventStart, DEventEnd, DTotalEventSpeedingTime, EventSpeedingTimeInSeconds, DLimit, DStateLimit, DMax, EquipTypeQualifier, NDAssetID, NDFleet, NDDate, NDDriveTime, NDTotalDriveTimeInSeconds, SpeedPercentage, MilesSpeeding, CLatLong, CMapLink, CLocation, CMaxReportedSpeed, hlvl1no, hlvl1name, hlvl2no, hlvl2name, hlvl3no, hlvl3name, hlvl9no, hlvl9name, asset_id, asset_descr, equip_type, equiptype_code, insp_fleet, MaxSpdStartTime, MaxSpdEndTime, cast('Y' as char(1)) SpeedingEvent
from cteSpeedReport cteSR
where   
    (EquipTypeQualifier = 'Y' 
    AND ((CLocation = 'Michigan' AND 
            (DLimit = 70 AND DMax >= 70)
            OR (DLimit = 65 AND DMax >= 71.5)
            OR (DLimit = 60 AND DMax > 66)
            OR (DLimit <= 55 AND DMax >= (DLimit * 1.10)))
        OR (CLocation = 'Indiana' AND
            (DLimit = 70 AND DMax > 71.5)
            OR (DLimit = 65 AND DMax > 71.5)
            OR (DLimit <= 55 AND DMax >= (DLimit * 1.10)))))
    OR (DMax >= (DLimit * 1.10))
UNION
SELECT DISTINCT DStartDate, DEndDate, DAssetID, DFleet, (DMax - DStateLimit) as DMaxOver, DEventStart, DEventEnd, DTotalEventSpeedingTime, EventSpeedingTimeInSeconds, DLimit, DStateLimit, DMax, EquipTypeQualifier, NDAssetID, NDFleet, NDDate, NDDriveTime, NDTotalDriveTimeInSeconds, SpeedPercentage, MilesSpeeding, CLatLong, CMapLink, CLocation, CMaxReportedSpeed, hlvl1no, hlvl1name, hlvl2no, hlvl2name, hlvl3no, hlvl3name, hlvl9no, hlvl9name, asset_id, asset_descr, equip_type, equiptype_code, insp_fleet, MaxSpdStartTime, MaxSpdEndTime, cast('N' as char(1)) SpeedingEvent
from cteSpeedReport cteSRN
where   
    (EquipTypeQualifier = 'Y'
    AND ((CLocation = 'Michigan' AND 
            (DLimit = 70 AND DMax < 70)
            OR (DLimit = 65 AND DMax < 71.5)
            OR (DLimit = 60 AND DMax <= 66)
            OR (DLimit <= 55 AND DMax < (DLimit * 1.10)))
        OR (CLocation = 'Indiana' AND
            (DLimit = 70 AND DMax <= 71.5)
            OR (DLimit = 65 AND DMax <= 71.5)
            OR (DLimit <= 55 AND DMax < (DLimit * 1.10))))
    )
    OR (DMax < (DLimit * 1.10))
) a
where
    a.NDTotalDriveTimeInSeconds =
    (SELECT sr.NDTotalDriveTimeInSeconds FROM cteSpeedReport sr
    where sr.DStartDate = a.DStartDate and sr.DFleet = a.DFleet
    )
order by SpeedingEvent desc, DStartDate, hlvl9name, DFleet, DEventStart

任何帮助将不胜感激。

【问题讨论】:

  • 获得答案的最佳选择是添加一个SQLFiddle,其中包含一个小数据集以及基于该数据集的所需结果。

标签: sql sql-server tsql subquery common-table-expression


【解决方案1】:

我认为问题出在您的 WHERE 子句中,子查询返回多个结果 - 给出 .

WHERE a.NDTotalDriveTimeInSeconds =
  (SELECT sr.NDTotalDriveTimeInSeconds FROM cteSpeedReport sr
  WHERE sr.DStartDate = a.DStartDate AND sr.DFleet = a.DFleet )

您可以将其更改为 MAX 或 SUM 或向 WHERE 子句添加更多条件 - 取决于逻辑的工作方式。

WHERE a.NDTotalDriveTimeInSeconds =
  (SELECT SUM(sr.NDTotalDriveTimeInSeconds) FROM cteSpeedReport sr
  WHERE sr.DStartDate = a.DStartDate AND sr.DFleet = a.DFleet )

另一方面,您可以过滤一般结果,然后使用 CASE 语句确定 YN 的strong>SpeedingEvent 列。

SELECT DISTINCT
     [List of Fields]
FROM (
    SELECT DISTINCT DStartDate, DEndDate, DAssetID, DFleet, (DMax - DStateLimit) as DMaxOver, DEventStart, DEventEnd, DTotalEventSpeedingTime, 
            EventSpeedingTimeInSeconds, DLimit, DStateLimit, DMax, EquipTypeQualifier, NDAssetID, NDFleet, NDDate, NDDriveTime, NDTotalDriveTimeInSeconds, 
            SpeedPercentage, MilesSpeeding, CLatLong, CMapLink, CLocation, CMaxReportedSpeed, hlvl1no, hlvl1name, hlvl2no, hlvl2name, hlvl3no, 
            hlvl3name, hlvl9no, hlvl9name, asset_id, asset_descr, equip_type, equiptype_code, insp_fleet, MaxSpdStartTime, MaxSpdEndTime, 
            CAST(
            CASE WHEN (CLocation = 'Michigan' AND (DLimit = 70 AND DMax < 70)
                        OR (DLimit = 65 AND DMax < 71.5)
                        OR (DLimit = 60 AND DMax <= 66)
                        OR (DLimit <= 55 AND DMax < (DLimit * 1.10)))
                    OR (CLocation = 'Indiana' AND (DLimit = 70 AND DMax <= 71.5)
                        OR (DLimit = 65 AND DMax <= 71.5)
                        OR (DLimit <= 55 AND DMax < (DLimit * 1.10)))
                THEN 'Y' ELSE 'N' END AS CHAR(1)) SpeedingEvent
    FROM cteSpeedReport cteSR
    WHERE   
        EquipTypeQualifier = 'Y' 
) a
WHERE a.NDTotalDriveTimeInSeconds = 
    (SELECT SUM(sr.NDTotalDriveTimeInSeconds) 
        FROM cteSpeedReport sr
        WHERE sr.DStartDate = a.DStartDate AND sr.DFleet = a.DFleet )
ORDER BY SpeedingEvent DESC, DStartDate, hlvl9name, DFleet, DEventStart

【讨论】:

  • 感谢 Hannover Fist 抽出宝贵时间回复。我接受了您不使用 UNION 并使用 CASE 语句来确定 SpeedingEvent 列的 Y 或 N 的建议。虽然这不是解决办法,但它让我朝着一个让我想出解决方案的方向前进。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-15
  • 2015-09-26
相关资源
最近更新 更多