我有以下SQL脚本,它是使用ADO针对SQL Server 2000数据库从Excel VBA运行的。
我遇到的问题是,虽然脚本中只有一个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 :(得分:0)
我会在临时表的末尾添加一个同位素列(虚拟列),这样当您看到三个记录集时,您可以询问列名称以查看它们来自何处。当您从配置文件中获取SQL并直接在SSMS中运行时会发生什么?你只得到一个结果集吗?
答案 1 :(得分:0)
我终于找到了这个问题,并认为我会报告回来。问题在于脚本中的两个聚合函数中的NULL值。这种情况偶尔发生的原因是因为数据不断变化。
尽管SQL Server“静默地”处理问题,但它确实会产生警告,ADO将其视为记录集,尽管在我的情况下(可能是每种情况)这些记录集都已关闭,因此无法实际查看它们包含的内容或产生它们的内容。 / p>
我没有用ISNULL()逻辑重写SQL脚本,而是选择仅包括
SET ANSI_WARNINGS OFF
脚本顶部的语句。这可以防止报告警告,因此ADO不会产生这些额外的不需要的记录集。
失望我没有早点发现这一点,但至少我学会了一些新东西。 :)