Я написал этот курсор для отчета комиссии. Что происходит, так это то, что комиссия поступает в одну таблицу, записи - в другую таблицу. Я сопоставляю два на основе определенных критериев (точное совпадение недоступно). Проблема в том, что там, где существуют записи, есть дубликаты. Когда я сопоставляю комиссию с таблицей records
, это может привести к получению этих дубликатов. Таким образом, представитель получает больше. С другой стороны, в таблице комиссий также есть дубликаты, но они действительны, потому что они просто означают, что счет был оплачен за 2 месяца.
Я написал этот запрос, но его выполнение занимает более 5 минут. У меня 50 000 записей в таблице записей и 100 000 в таблице комиссий. Есть ли способ улучшить этот курсор?
/* just preparation of cursor, this is not time consuming */
CREATE TABLE #result
(
repid INT,
AccountNo VARCHAR(100),
supplier VARCHAR(15),
CompanyName VARCHAR(200),
StartDate DATETIME,
EndDate DATETIME,
Product VARCHAR(25),
commodity VARCHAR(25),
ContractEnd DATETIME,
EstUsage INT,
EnrollStatus VARCHAR(10),
EnrollDate DATETIME,
ActualEndDate DATETIME,
MeterStart DATETIME,
MeterEnd DATETIME,
ActualUsage INT
)
DECLARE @AccountNo VARCHAR(100)
DECLARE @supplier VARCHAR(10)
DECLARE @commodity VARCHAR(15)
DECLARE @meterstart DATETIME
DECLARE @meterEnd DATETIME
DECLARE @volume FLOAT
DECLARE @RepID INT
DECLARE @Month INT
DECLARE @Year INT
SET @repID = 80
SET @Month = 1
SET @year = 2012
/* the actual cursor */
DECLARE commission_cursor CURSOR FOR
SELECT AccountNo,
supplier,
commodity,
meterStart,
MeterEnd,
Volume
FROM commission
WHERE Datepart(m, PaymentDate) = @Month
AND Datepart(YYYY, PaymentDate) = @Year
OPEN commission_cursor
FETCH next FROM commission_cursor INTO @AccountNo, @supplier, @commodity, @MeterStart, @MeterEnd, @Volume;
WHILE @@fetch_status = 0
BEGIN
IF EXISTS (SELECT id
FROM Records
WHERE AccountNo = @AccountNo
AND supplier = @supplier
AND Commodity = @commodity
AND RepID = @repID)
INSERT INTO #result
SELECT TOP 1 RepID,
AccountNo,
Supplier,
CompanyName,
[Supplier Start Date],
[Supplier End Date],
Product,
Commodity,
[customer end date],
[Expected Usage],
EnrollStatus,
ActualStartDate,
ActualEndDate,
@meterstart,
@MeterEnd,
@volume
FROM Records
WHERE AccountNo = @AccountNo
AND supplier = @supplier
AND Commodity = @commodity
AND RepID = @repID
AND @MeterStart >= Dateadd(dd, -7, ActualStartDate)
AND @meterEnd <= Isnull(Dateadd(dd, 30, ActualEndDate), '2015-12-31')
FETCH next FROM commission_cursor INTO @AccountNo, @supplier, @commodity, @MeterStart, @MeterEnd, @Volume;
END
SELECT *
FROM #result
/* clean up */
CLOSE commission_cursor
DEALLOCATE commission_cursor
DROP TABLE #result
Я прочитал ответ на Как ускорить курсор T-SQL?, для этого я переписываю этот запрос в виде таблицы. Но у меня есть еще один запрос, который использует соединение и быстро выполняется. Проблема в том, что он не может различать дубликаты в моей таблице records
.
Есть ли что-нибудь, что я могу сделать, чтобы сделать это быстрее. Это первичный вопрос. Если нет, есть ли у вас альтернативный способ сделать это.
Мне конкретно нужна помощь с
- Поможет ли использование представлений или процедур хранения
- У меня есть способ использовать кеш в курсоре, чтобы сделать его быстрее
- Любая другая опция в синтаксисе
FAST_FORWARD
? - person Andriy M   schedule 15.06.2012LOCAL STATIC READ_ONLY FORWARD_ONLY
— единственный способ повысить эффективность. (вполне вероятно, что вы можете сделать это вообще без цикла), но это хорошее начало. - person Aaron Bertrand   schedule 15.06.2012TOP 1
безORDER BY
? Вас действительно не волнует, какая совпадающая строка вRecords
вы получите? - person Aaron Bertrand   schedule 15.06.2012order by
, чтобы еще больше не перегружать курсор. В идеале да, я хочу его там. Но я уже фильтрую записи на основе того, попадают ли даты начала и окончания счетчика в эту запись, а затем выбираю только их. Если таких записей более 1, то можно использовать любую из них. - person Hammad Khan   schedule 15.06.2012select * from result
, кажется, не заботится о порядке. - person Aaron Bertrand   schedule 15.06.2012