2012-02-17 40 views
0

我有下面的SQL腳本,它是從Excel VBA使用ADO對SQL Server 2000數據庫運行的。多記錄集問題

我遇到的問題是,雖然在腳本中只有一個SELECT語句,但在執行.Open方法時,有時會收到三個記錄集。我有時會說,在場合和其他'平行'數據庫中,我只收到一個記錄集。

我知道所有關於.NextRecordset()方法等,但我想了解爲什麼我有三次返回記錄集,有時我只收到一次。我馬上要運行SQL跟蹤來查看是否會拋出任何想法,但像往常一樣,任何幫助或建議將不勝感激。

SET NOCOUNT ON 
DECLARE @RunDate VARCHAR(8) 

SET @RunDate = CONVERT(VARCHAR(8), DATEADD(d, -1 * 1, GETDATE()), 112) 

IF OBJECT_ID('tempdb..#ActiveOrders') IS NOT NULL DROP TABLE #ActiveOrders 
IF OBJECT_ID('tempdb..#ApplicableOrders') IS NOT NULL DROP TABLE #ApplicableOrders 
IF OBJECT_ID('tempdb..#FilterOut') IS NOT NULL DROP TABLE #FilterOut 

/*Temp table created as it has a self-join in the below query */ 
CREATE TABLE #ActiveOrders(
    order_id VARCHAR(30) 
    , instrument_id VARCHAR(30) 
    , side CHAR(1) 
    ) 

CREATE INDEX idx_ActiveOrders_orderId ON #ActiveOrders(order_id) 

/*Build dataset of all orders which have had activity on the run date or are in an Open status. Ignoring Program Trades.*/ 
INSERT INTO #ActiveOrders 
SELECT o1.order_id COLLATE Latin1_General_CI_AS 
     , o1.instrument_id 
     , o1.side 
FROM orders o1 
INNER JOIN desk d1 ON d1.desk_id = o1.investment_desk 
INNER JOIN (SELECT o0.order_id 
      FROM orders o0 
      WHERE ((LEFT(o0.added_datetime, 8) = @RunDate 
        OR LEFT(o0.approved_datetime, 8) = @RunDate) 
        OR (LEFT(o0.added_datetime, 8) <= @RunDate 
        AND o0.summary_status IN (1, 2, 3, 5, 8, 9))) /*Approved, Assigned, Acknowledged, Working, Partial, WorkingPartial*/ 
      UNION 
      (SELECT r0.order_id 
      FROM releases r0 
      WHERE LEFT(r0.added_datetime, 8) = @RunDate) 
      UNION 
      (SELECT e0.order_id 
      FROM executions e0 
      WHERE LEFT(e0.execution_datetime, 8) = @RunDate 
        OR LEFT(e0.allocated_datetime, 8) = @RunDate) 
      ) t1 ON o1.order_id = t1.order_id 
WHERE d1.location_id = 'LDEQ'  
     AND o1.summary_status <> 4 
     AND o1.list_id IS NULL /*Ignore program trades*/ 

/*This is now the actual dataset we are interested in. 
This is everything which could be a contender for aggregation.*/ 
CREATE TABLE #ApplicableOrders(
    order_id VARCHAR(30) 
    , instrument_id VARCHAR(30) 
    , side CHAR(1) 
    , approved_datetime DATETIME 
    , acknowledged_datetime DATETIME 
    , last_allocation_datetime DATETIME 
    , latest_status INT 
    , merged_orders VARCHAR(500) 
    , dealer VARCHAR(100) 
    , manager VARCHAR(100) 
    , limit_price FLOAT 
    , original_qty FLOAT 
    , executed_qty FLOAT 
    , trader_instruction TEXT 
    , dealer_note TEXT 
    ) 

CREATE INDEX idx_ApplicableOrders_orderId ON #ApplicableOrders(order_id) 
CREATE INDEX idx_ApplicableOrders_lastAllocation ON #ApplicableOrders(last_allocation_datetime) 
CREATE INDEX idx_ApplicableOrders_approved ON #ApplicableOrders(approved_datetime) 

/*All orders from #ActiveOrders where there are two or more orders which are for the same instrument and in the same direction.*/ 
INSERT INTO #ApplicableOrders 
SELECT o.order_id 
     , o.instrument_id 
     , o.side 
     , dbo.mglz_datetime(o.approved_datetime) 
     , dbo.mglz_datetime(o.ack_datetime) 
     , MAX(dbo.mglz_datetime(e.allocated_datetime)) "Last Allocation DateTime" 
     , o.summary_status 
     , o.merged_orders 
     , o.ack_id 
     , o.approver_id 
     , o.limit_price 
     , o.original_qty 
     , o.executed_qty_at 
     , CONVERT(VARCHAR(900), o.trader_instruction) 
     , CONVERT(VARCHAR(900), o.dealer_note) 
FROM orders o 
     INNER JOIN #ActiveOrders t ON o.order_id = t.order_id COLLATE Latin1_General_CI_AS 
     INNER JOIN #ActiveOrders s ON s.order_id <> o.order_id COLLATE Latin1_General_CI_AS 
             AND s.instrument_id = o.instrument_id COLLATE Latin1_General_CI_AS 
             AND s.side = o.side COLLATE Latin1_General_CI_AS 
     LEFT JOIN executions e ON e.order_id = o.order_id 
GROUP BY o.order_id 
     , o.instrument_id 
     , o.side 
     , o.approved_datetime 
     , o.ack_datetime 
     , o.summary_status 
     , o.merged_orders 
     , o.ack_id 
     , o.approver_id 
     , o.limit_price 
     , o.original_qty 
     , o.executed_qty_at 
     , CONVERT(VARCHAR(900), o.trader_instruction) 
     , CONVERT(VARCHAR(900), o.dealer_note) 

/*Filter out any orders where Order2.Approved_Date > Order1.Last_Release_Date AND Order1.Is_Complete 
Order1 is defined as the order which was approved first.*/ 
SELECT t1.* 
INTO #FilterOut 
FROM #ApplicableOrders t1 
WHERE EXISTS (SELECT 1 
       FROM 
        (SELECT order2.order_id 
        FROM (SELECT b.order_id 
            , b.instrument_id 
            , b.side 
            , b.approved_datetime 
            , b.last_allocation_datetime 
            , b.latest_status 
            , b.executed_qty 
            , b.original_qty 
          FROM #ApplicableOrders b 
          WHERE b.approved_datetime = (SELECT MIN(b1.approved_datetime) FirstApproval 
                 FROM #ApplicableOrders b1 
                 WHERE b1.instrument_id = b.instrument_id 
                  AND b1.side = b.side) 
         ) order1 
        INNER JOIN 
         (SELECT c.order_id 
           , c.instrument_id 
           , c.side 
           , c.approved_datetime 
          FROM #ApplicableOrders c 
          WHERE c.approved_datetime > (SELECT MIN(c1.approved_datetime) FirstApproval 
                 FROM #ApplicableOrders c1 
                 WHERE c1.instrument_id = c.instrument_id 
                  AND c1.side = c.side) 
         ) order2 
        ON order1.instrument_id = order2.instrument_id 
         AND order1.side = order2.side 
         AND order2.approved_datetime > order1.last_allocation_datetime 
         AND (order1.latest_status = 6 OR order1.executed_qty = order1.original_qty)) filter1 
       WHERE t1.order_id = filter1.order_id) 

/*Filter out any orders where Order2.Acknowledged_Date > Order1.Last_Allocation_Date.*/ 
INSERT INTO #FilterOut 
    SELECT t1.* 
    FROM #ApplicableOrders t1 
    WHERE EXISTS (SELECT 1 
        FROM 
         (SELECT order2.order_id 
         FROM (SELECT b.order_id 
            , b.instrument_id 
            , b.side 
            , b.approved_datetime 
            , b.last_allocation_datetime 
          FROM #ApplicableOrders b 
          WHERE b.approved_datetime = (SELECT MIN(b1.approved_datetime) FirstApproval 
                 FROM #ApplicableOrders b1 
                 WHERE b1.instrument_id = b.instrument_id 
                  AND b1.side = b.side) 
          ) order1 
         INNER JOIN 
          (SELECT c.order_id 
            , c.instrument_id 
            , c.side 
            , c.approved_datetime 
            , c.acknowledged_datetime 
           FROM #ApplicableOrders c 
           WHERE c.approved_datetime > (SELECT MIN(c1.approved_datetime) FirstApproval 
                  FROM #ApplicableOrders c1 
                  WHERE c1.instrument_id = c.instrument_id 
                   AND c1.side = c.side) 
          ) order2 
         ON order1.instrument_id = order2.instrument_id 
          AND order1.side = order2.side 
          AND order2.acknowledged_datetime > order1.last_allocation_datetime) filter2 
        WHERE t1.order_id = filter2.order_id) 
    AND NOT EXISTS (SELECT 1 
        FROM #FilterOut a1 
        WHERE a1.order_id = t1.order_id) 

/*Filter any 'single' orders. I.e. all 'matching' orders have been excluded so the instrument/direction combination is not applicable for Aggregation.*/ 
INSERT INTO #FilterOut 
    SELECT t1.* 
    FROM #ApplicableOrders t1 INNER JOIN (SELECT DISTINCT t.instrument_id 
                  , t.side 
              FROM #ApplicableOrders t 
              INNER JOIN #FilterOut a ON t.instrument_id = a.instrument_id 
                       AND t.side = a.side 
              GROUP BY t.instrument_id 
                , t.side 
              HAVING COUNT(t.instrument_id) > 1) t2 ON t1.instrument_id = t2.instrument_id 
                         AND t1.side = t2.side 
    WHERE NOT EXISTS (SELECT 1 
         FROM #FilterOut a1 
         WHERE a1.order_id = t1.order_id) 

/*Final Report*/ 
/*A list of all orders where aggregation could have possibly occurred but didn't.*/ 
SELECT t1.order_id "Order ID" 
     , i.name "Name" 
     , t1.side "B/S" 
     , userDealer.short_name "Dlr" 
     , userManager.short_name "FM" 
     , t1.limit_price "Limit" 
     , t1.approved_datetime "Order Approved" 
     , t1.acknowledged_datetime "Order Acknowledged" 
     , t1.last_allocation_datetime "Last Execution" 
     , t1.merged_orders "Merged Orders" 
     , m.description "Status" 
     , t1.dealer_note "Dealer Note" 
     , t1.trader_instruction "Trader Instruction" 
FROM #ApplicableOrders t1 
    INNER JOIN instrument i ON t1.instrument_id = i.instrument_id COLLATE Latin1_General_CI_AS 
    INNER JOIN mnemonics m ON t1.latest_status = m.value AND m.attribute = 'order_summary_status' 
    LEFT JOIN users userDealer ON userDealer.user_id = t1.dealer COLLATE Latin1_General_CI_AS 
    LEFT JOIN users userManager ON userManager.user_id = t1.manager COLLATE Latin1_General_CI_AS 
WHERE NOT EXISTS (SELECT 1 
        FROM #FilterOut t2 
        WHERE t1.order_id = t2.order_id) 
ORDER BY t1.name 
     , t1.side 
     , t1.approved_datetime 

IF OBJECT_ID('tempdb..#ActiveOrders') IS NOT NULL DROP TABLE #ActiveOrders 
IF OBJECT_ID('tempdb..#ApplicableOrders') IS NOT NULL DROP TABLE #ApplicableOrders 
IF OBJECT_ID('tempdb..#FilterOut') IS NOT NULL DROP TABLE #FilterOut 
+0

我應該補充一點,當我收到3個記錄集時,前兩個處於關閉狀態,表示沒有要返回的記錄。 – markblandford 2012-02-17 12:45:28

+0

在用SQL跟蹤找到一個死衚衕並玩SQL後,我認爲這個問題似乎與兩個WHERE EXISTS(SELECT 1 ... – markblandford 2012-02-17 17:13:17

回答

0

我終於找到了問題,並認爲我會回報。問題是腳本中兩個聚合函數中的NULL值。這只是偶爾發生的原因是因爲數據不斷變化。

雖然SQL Server處理這個問題「默默地」,但確實會產生ADO認爲是記錄集的警告,儘管在我的情況下(可能是每種情況)這些記錄集都是關閉的,因此無法真正看到它們包含什麼或產生了什麼。

而不是重新編寫具有ISNULL()邏輯的SQL腳本,我都選擇簡單地包括在腳本的頂部

SET ANSI_WARNINGS OFF 

聲明。這可以防止報告警告,因此ADO不會產生這些額外的不需要的記錄集。

失望我以前沒有發現,但至少我學到了新東西。 :)

+0

好解決方案,請接受你自己的答案。 – 2012-02-21 13:31:36

0

我會同位素列(虛擬列)添加到您的臨時表的末尾這樣,當你看到三個記錄集,你可以詢問列名看到他們來自何處。當從配置文件中獲取SQL並直接在SSMS中運行時會發生什麼?你只有一個結果集?

+0

)感謝您的建議,但返回的三個記錄集中有兩個在一個關閉的狀態,所以我不能做任何事情與他們這是爲什麼我一直在努力找出是什麼造成他們在SSMS運行時,我似乎只得到一個記錄集回來我相信這個問題是與WHERE EXISTS語句(因爲我有兩個[他們是SELECT語句]),但不幸的是,這個問題已經解決了[現在],所以我不能證明它。一旦我知道任何一種方式,我會發布我的結果 – markblandford 2012-02-20 09:42:29