我继承了一个我正在为报告系统工作的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,但是作业没有收到结束时间,因为兄弟姐妹后来失败了。这会创建一个状态,其中状态仍然为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)
如果我想要做的事情有一个共同的术语或名称,也许有人可以将它添加到标题中?
答案 0 :(得分:2)
一个侧面点 - 您是否提供了生产代码摘录的代码段?如果是这样,您可以仅使用ConfirmFailed
条件替换整个块,因为它对您显示的所有WHERE
条件都是通用的,并且可以单独满足它。
虽然它没有直接回答您提出的问题,但简化代码的方法是在预处理步骤中计算每个Failed
指标的值 - 具体取决于您的环境,这可能是CTE,临时表或视图。这样,所有逻辑都在一个地方 - 如果在查询中多次需要该值,这在例如SELECT
和WHERE
子句中非常有用。
答案 1 :(得分:1)
[是]有一个共同的术语或名称 我想做什么......?
抽象?
您可以将每个CreateFailed = ..., TransmitFailed = ...
等逻辑隐藏到自己的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
);
我不确定这对性能有好处,但可读性是目标,无论如何这个报告都可以离线运行。