3

何があっても行を表示しようとしているクエリがあります。クエリは、返されるデータがある場合に必要な情報の正しい情報を返しますが、すべての行がnullの場合、明らかに何も得られません。そうでない場合は、何もない代わりに、すべて0を返す行が必要です。

私はこれを使って説明しようisnull()coalesce()しましたが、どうやら正しくやっていないようです。以下は、この目的のために調整する必要がある私の基本クエリです。

SELECT
    Vendor
    ,SUM(TotalAssigned) as 'Total Production Assigned Not Completed'
    ,SUM(AssignedFees) as 'Work in process Fees'
    ,SUM(TotalSubmitted) as 'Total Production Submitted'
    ,SUM(SubmittedFees) as 'Submitted Production Fees'
FROM(
    SELECT
        distinct 
        v.ContactFirstName+' '+v.ContactLastName AS Vendor
        ,oi.orderid, oi.orderitemid
        ,CASE WHEN  oi.QueueID > 0 and oi.lastmilestoneid < 70 THEN 1 ELSE 0 END AS TotalAssigned
        ,CASE WHEN  oi.QueueID > 0 and oi.lastmilestoneid < 70 THEN dbo.GetAdjustedVendorFee(oi.OrderID, oi.OrderItemID) END AS AssignedFees
        ,CASE WHEN oim.MilestoneID = 70 THEN 1 ELSE 0 END AS TotalSubmitted
        ,CASE WHEN oim.MilestoneID = 70 THEN dbo.GetAdjustedVendorFee(oi.OrderID, oi.OrderItemID) END AS SubmittedFees

    FROM
    OrderItems oi
    LEFT JOIN OrderItemMilestones oim ON oim.OrderID = oi.OrderID and oim.OrderItemID = oi.OrderItemID
    LEFT JOIN Vendors v ON v.VendorID = oi.VendorID
    WHERE
    oim.MilestoneDate BETWEEN dbo.TruncateDate(dateadd(dd, -1, Current_Timestamp)) and dbo.TruncateDate(Current_Timestamp)
    and oi.VendorID in (105144) 
    and oi.productid not in (105)
)x

GROUP BY Vendor
4

3 に答える 3

7

1つの方法は、式をCTEでラップしてUNION ALLから、

UNION ALL SELECT NULL, 0,0,0,0 WHERE NOT EXISTS(SELECT * FROM CTE)

例えば

WITH CTE AS 
(SELECT
    Vendor
    ,SUM(TotalAssigned) as 'Total Production Assigned Not Completed'
    ,SUM(AssignedFees) as 'Work in process Fees'
    ,SUM(TotalSubmitted) as 'Total Production Submitted'
    ,SUM(SubmittedFees) as 'Submitted Production Fees'
FROM(
    SELECT
        distinct 
        v.ContactFirstName+' '+v.ContactLastName AS Vendor
        ,oi.orderid, oi.orderitemid
        ,CASE WHEN  oi.QueueID > 0 and oi.lastmilestoneid < 70 THEN 1 ELSE 0 END AS TotalAssigned
        ,CASE WHEN  oi.QueueID > 0 and oi.lastmilestoneid < 70 THEN dbo.GetAdjustedVendorFee(oi.OrderID, oi.OrderItemID) END AS AssignedFees
        ,CASE WHEN oim.MilestoneID = 70 THEN 1 ELSE 0 END AS TotalSubmitted
        ,CASE WHEN oim.MilestoneID = 70 THEN dbo.GetAdjustedVendorFee(oi.OrderID, oi.OrderItemID) END AS SubmittedFees

    FROM
    OrderItems oi
    LEFT JOIN OrderItemMilestones oim ON oim.OrderID = oi.OrderID and oim.OrderItemID = oi.OrderItemID
    LEFT JOIN Vendors v ON v.VendorID = oi.VendorID
    WHERE
    oim.MilestoneDate BETWEEN dbo.TruncateDate(dateadd(dd, -1, Current_Timestamp)) and dbo.TruncateDate(Current_Timestamp)
    and oi.VendorID in (105144) 
    and oi.productid not in (105)
)x

GROUP BY Vendor)
SELECT * FROM CTE
UNION ALL SELECT NULL, 0,0,0,0  WHERE NOT EXISTS(SELECT * FROM CTE)

これは、それほど複雑ではないステートメントのデモです

于 2013-01-30T21:59:44.280 に答える
2

別の方法は、クエリを派生テーブルとして無条件にデフォルト値の行に左結合し、ISNULLまたはCOALESCEを使用してサブクエリからデータを返すか、デフォルトにフォールバックすることです。

SELECT
     ISNULL(sub.Vendor                                   , def.Vendor                                   ) AS Vendor
    ,ISNULL(sub.[Total Production Assigned Not Completed], def.[Total Production Assigned Not Completed]) AS 'Total Production Assigned Not Completed'
    ,ISNULL(sub.[Work in process Fees]                   , def.[Work in process Fees]                   ) AS 'Work in process Fees'
    ,ISNULL(sub.[Total Production Submitted]             , def.[Total Production Submitted]             ) AS 'Total Production Submitted'
    ,ISNULL(sub.[Submitted Production Fees]              , def.[Submitted Production Fees]              ) AS 'Submitted Production Fees'
FROM (
    SELECT
        '' AS Vendor
        ,0 AS 'Total Production Assigned Not Completed'
        ,0 AS 'Work in process Fees'
        ,0 AS 'Total Production Submitted'
        ,0 AS 'Submitted Production Fees'
) def
LEFT JOIN (
    your query
) sub
ON 1=1  -- unconditionally; almost the same as CROSS JOIN
;

これはほとんどクロスジョインに似ていますが、後者とは異なり、空でないデータセットを返すことが保証されています。

于 2013-01-30T22:30:57.973 に答える
2

これはより簡単な解決策になる可能性があります(@AndriyMのリミックス):

SELECT
    Vendor
    ,SUM(TotalAssigned) as 'Total Production Assigned Not Completed'
    ,SUM(AssignedFees) as 'Work in process Fees'
    ,SUM(TotalSubmitted) as 'Total Production Submitted'
    ,SUM(SubmittedFees) as 'Submitted Production Fees'
FROM (
    SELECT
        distinct 
        v.ContactFirstName+' '+v.ContactLastName AS Vendor
        ,oi.orderid, oi.orderitemid
        ,CASE WHEN  oi.QueueID > 0 and oi.lastmilestoneid < 70 THEN 1 ELSE 0 END AS TotalAssigned
        ,CASE WHEN  oi.QueueID > 0 and oi.lastmilestoneid < 70 THEN dbo.GetAdjustedVendorFee(oi.OrderID, oi.OrderItemID) END AS AssignedFees
        ,CASE WHEN oim.MilestoneID = 70 THEN 1 ELSE 0 END AS TotalSubmitted
        ,CASE WHEN oim.MilestoneID = 70 THEN dbo.GetAdjustedVendorFee(oi.OrderID, oi.OrderItemID) END AS SubmittedFees

    FROM
    OrderItems oi
    LEFT JOIN OrderItemMilestones oim ON oim.OrderID = oi.OrderID and oim.OrderItemID = oi.OrderItemID
    LEFT JOIN Vendors v ON v.VendorID = oi.VendorID
    WHERE
    oim.MilestoneDate BETWEEN dbo.TruncateDate(dateadd(dd, -1, Current_Timestamp)) and dbo.TruncateDate(Current_Timestamp)
    and oi.VendorID in (105144) 
    and oi.productid not in (105)
) x RIGHT JOIN (SELECT 1 as ONE) T ON 1=1
GROUP BY Vendor

sqlfiddlehttp ://sqlfiddle.com/#!6/189a3/1024

于 2013-01-31T09:27:07.277 に答える