Хранимая процедура отчетности - как избежать дублирования? - PullRequest
1 голос
/ 26 января 2010

Я пишу хранимую процедуру отчетности. Я хочу получить количество неподтвержденных и неоплаченных заказов на покупку с возможностью (опционально) фильтрации на CustomerID.

То, что у меня есть ниже, работает, как и ожидалось, но я волнуюсь, что а) это медленно и б) есть дублирование в CustomerID части предложения WHERE.

Как бы вы написали этот сохраненный процесс, Stack Overflow?

SELECT 
  (SELECT COUNT(*)
   FROM PurchaseOrder
   WHERE AcknowledgmentStatus <> 'Complete'
   AND (@CustID = 0 OR CustomerID = @CustID)
  ) AS NonAckd,
  (SELECT COUNT(*)
   FROM PurchaseOrder
   WHERE InvoiceStatus <> 'Complete'
   AND (@CustID = 0 OR CustomerID = @CustID)
  ) AS NonInvoiced

Ответы [ 3 ]

2 голосов
/ 26 января 2010

Примерно так:

SELECT Sum(Case When AcknowledgmentStatus <> 'Complete' Then 1 ELSE 0 END) as NonAckd
      ,Sum(Case When InvoiceStatus <> 'Complete'        Then 1 ELSE 0 END) as NonInvoiced 
  FROM PurchaseOrder 
 WHERE CustomerID = IsNull(NullIf(@CustID, 0), CustomerID) 
2 голосов
/ 26 января 2010

Я не уверен на 100%, что вы ищете, но вы могли бы упростить клиентскую часть следующим образом: (не проверено из [утомленной] памяти)

set @custID = nullif(@custID,0)

SELECT 
  (SELECT COUNT(*)
   FROM PurchaseOrder
   WHERE AcknowledgmentStatus <> 'Complete'
   AND ( CustomerID = isnull(@CustID,CustomerID) )
  ) AS NonAckd,
  (SELECT COUNT(*)
   FROM PurchaseOrder
   WHERE InvoiceStatus <> 'Complete'
   AND ( CustomerID = isnull(@CustID,CustomerID) )
  ) AS NonInvoiced
1 голос
/ 26 января 2010

Вы не можете использовать:

  • COUNT, потому что он будет считать все строки (1 или 0 не равен нулю, поэтому он считает их)
  • COUNT DISTINCT даст 2 (только значения 1 и 0)

Если вы удалите проверки статуса, то, конечно, будете работать быстрее, если сможете справиться с нулями.

SELECT
    CASE WHEN AcknowledgmentStatus <> 'Complete' THEN 1 ELSE 0 END AS NonAckd,
    CASE WHEN InvoiceStatus <> 'Complete' THEN 1 ELSE 0 END AS NonInvoiced,
FROM
    PurchaseOrder
WHERE
    (AcknowledgmentStatus <> 'Complete' OR  InvoiceStatus <> 'Complete') --optional
    AND
    (@CustID = 0 OR CustomerID = @CustID)
...