4

我继承了我正在为报告系统工作的一段 SQL。该系统以采购订单为中心,以及何时创建、传输、确认和确认。这些状态是进步状态。我正在查看的 SQL 片段如下所示,来自 WHERE 子句:

OR (CreateJob.endtime is NULL and DATEDIFF(hour, buy_date, getdate()) > Vendor.expected_create_hours)
OR (TransmitJob.endtime is NULL and DATEDIFF(hour, CreateJob.endtime, getdate()) > Vendor.expected_transmit_hours)
OR (AcknowledgeJob.endtime is NULL and DATEDIFF(hour, TransmitJob.endtime, getdate()) > Vendor.expected_acknowledge_hours)
OR (ConfirmJob.endtime is NULL and DATEDIFF(hour, AcknowledgeJob.endtime, getdate()) > Vendor.expected_confirm_hours)

我发现 CreateJob 可能因为作业失败而没有结束时间。但是,作业可以执行多个采购订单,因此有时实际创建了给定的采购订单,但作业没有收到结束时间,因为后来兄弟失败了。这会创建一个场景,其中 PO 的状态仍在进行中,但它仍然显示在此问题报告中,因为 CreateJob.endtime 为 NULL。

首先,上面的系统和架构存在一些明显的错误,但这是与我目前正在解决的问题不同的问题。

不过,我似乎可以通过将渐进式检查添加为 AND 语句来修复报告。所以第一次检查 CreateJob 也发生了变化:

(     (CreateJob.endtime is NULL and DATEDIFF(hour, buy_date, getdate()) > Vendor.expected_create_hours) 
  AND (TransmitJob.endtime is NULL and DATEDIFF(hour, CreateJob.endtime, getdate()) > Vendor.expected_transmit_hours) 
  AND (AcknowledgeJob.endtime is NULL and DATEDIFF(hour, TransmitJob.endtime, getdate()) > Vendor.expected_acknowledge_hours) 
  AND (ConfirmJob.endtime is NULL and DATEDIFF(hour, AcknowledgeJob.endtime, getdate()) > Vendor.expected_confirm_hours))

这是丑陋的,并开始混淆事物以被遗忘。有什么方法可以在 SQL 中执行与以下等效的操作吗?基本上是某种宏或#define系统?

CreateFailed = (CreateJob.endtime is NULL and DATEDIFF(hour, buy_date, getdate()) > Vendor.expected_create_hours)
TransmitFailed = (TransmitJob.endtime is NULL and DATEDIFF(hour, CreateJob.endtime, getdate()) > Vendor.expected_transmit_hours)
AcknowledgeFailed = (AcknowledgeJob.endtime is NULL and DATEDIFF(hour, TransmitJob.endtime, getdate()) > Vendor.expected_acknowledge_hours)
ConfirmFailed = (ConfirmJob.endtime is NULL and DATEDIFF(hour, AcknowledgeJob.endtime, getdate()) > Vendor.expected_confirm_hours)


OR (CreateFailed AND TransmitFailed AND AcknowledgeFailed AND ConfirmFailed)
OR (TransmitFailed AND AcknowledgeFailed AND ConfirmFailed)
OR (AcknowledgeFailed AND ConfirmFailed)
OR (ConfirmFailed)

如果我正在尝试做的事情有一个通用术语或名称,也许有人可以将它添加到标题中?

4

2 回答 2

2

附带一点 - 您提供的代码片段是生产代码的摘录吗?如果是这样,您可以只用条件替换整个块ConfirmFailed,因为它对WHERE您显示的所有条件都是通用的,并且可以自行满足。

虽然它不能直接回答您提出的问题,但简化代码的一种方法是Failed在预处理步骤中计算每个指标的值 - 根据您的环境,这可能是 CTE、临时表或看法。这样,所有逻辑都在一个地方——如果在查询中多次需要该值,这特别有用——例如在SELECTandWHERE子句中。

于 2010-07-07T07:57:12.233 回答
1

[是] 我正在尝试做的事情有一个通用术语或名称......?

抽象?

您可以将每个CreateFailed = ..., TransmitFailed = ..., etc 逻辑隐藏到它自己的VIEW或 CTE 中,然后您的主查询只能查看这些表之一中是否存在作业,例如(伪 SQL):

SELECT Jobs.job_ID, ...
  FROM Jobs
 WHERE EXISTS (
               SELECT * 
                 FROM CreatedFailedJobs AS T1
                WHERE Jobs.job_ID = T1.job_ID
               )
       OR EXISTS (
                  SELECT * 
                    FROM TransmitFailedJobs AS T1
                   WHERE Jobs.job_ID = T1.job_ID
                  )
       OR EXISTS (
                  SELECT * 
                    FROM AcknowledgeFailedJobs AS T1
                   WHERE Jobs.job_ID = T1.job_ID
                  )
       OR EXISTS (
                  SELECT * 
                    FROM ConfirmFailedJobs AS T1
                   WHERE Jobs.job_ID = T1.job_ID
                  );

这是扩展的 CTE 想法(伪 SQL):

WITH CreateFailedJobs (job_ID, ...)
AS
(
 SELECT Jobs.job_ID, ...
   FROM ...
  WHERE CreateJob.endtime is NULL 
        AND DATEDIFF(hour, .SomeTable.buy_date, getdate()) 
               > Vendor.expected_create_hours
), 
TransmitFailedJobs (job_ID, ...)
AS
(
 SELECT Jobs.job_ID, ...
   FROM ...
  WHERE TransmitJob.endtime is NULL 
        AND DATEDIFF(hour, CreateJob.endtime, getdate()) 
               > Vendor.expected_transmit_hours
), 
AcknowledgeFailedJobs (job_ID, ...)
AS
(
 SELECT Jobs.job_ID, ...
   FROM ...
  WHERE AcknowledgeJob.endtime is NULL 
        AND DATEDIFF(hour, TransmitJob.endtime, getdate()) 
               > Vendor.expected_acknowledge_hours
), 
ConfirmFailedJobs (job_ID, ...)
AS
(
 SELECT Jobs.job_ID, ...
   FROM ...
  WHERE ConfirmJob.endtime is NULL 
        AND DATEDIFF(hour, AcknowledgeJob.endtime, getdate()) 
               > Vendor.expected_confirm_hours)
)
SELECT Jobs.job_ID, ...
  FROM Jobs
 WHERE EXISTS (
               SELECT * 
                 FROM CreatedFailedJobs AS T1
                WHERE Jobs.job_ID = T1.job_ID
               )
       OR EXISTS (
                  SELECT * 
                    FROM TransmitFailedJobs AS T1
                   WHERE Jobs.job_ID = T1.job_ID
                  )
       OR EXISTS (
                  SELECT * 
                    FROM AcknowledgeFailedJobs AS T1
                   WHERE Jobs.job_ID = T1.job_ID
                  )
       OR EXISTS (
                  SELECT * 
                    FROM ConfirmFailedJobs AS T1
                   WHERE Jobs.job_ID = T1.job_ID
                  );

我不确定这对性能有好处,但可读性是目标,无论如何这个报告可以离线运行。

于 2010-07-07T08:36:04.830 回答