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が実際に作成されたが、後で兄弟が失敗したためにジョブが終了時刻を受け取らない場合があります。これにより、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は、前処理ステップで各インジケーターの値を1回計算することです。環境に応じて、これはCTE、一時テーブル、または見る。このように、すべてのロジックが1つの場所にあります。これは、たとえば、 SELECTand句で値がクエリで複数回必要な場合に特に役立ちます。WHERE

于 2010-07-07T07:57:12.233 に答える
1

[は]私がやろうとしていることには一般的な用語や名前があります...?

抽象化?

CreateFailed = ..., TransmitFailed = ...各ロジックを独自のCTEまたはCTEに非表示にするとVIEW、メインクエリは、ジョブがこれらのテーブルの1つに存在するかどうかを確認するだけで済みます(疑似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 に答える