CTE(Common Table Expressions)を使用して秒単位で実行するように減らすことができた約数分間長く実行されるカーソルがあります。カーソルの各反復で上位10個の値を取得する必要があるという条件が与えられるまで、結果セットは同一でした。これは、セットベースのロジックでは実行できません。
カーソルベースのロジックを次のように想定します。
_SET @mycurse = CURSOR FOR
SELECT value FROM sometable
OPEN @mycurse
FETCH NEXT FROM @mycurse INTO @SomeVariable
IF @@FETCH_STATUS <> 0
Print 'Error in the Cursor Fetch Statement'
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @TOP10
SELECT Value1,Value2,Value3,Value4
FROM (
select Value1,Value1,Value3,Value4 from BaseTable where SomeVariable=@SomeVariable
)
FETCH NEXT FROM @mycurse INTO @SomeVariable
END
CLOSE @mycurse
_
そして、CTEベースのソリューションは次のようになります。
_;With myCTE(value)
as
(
SELECT value FROM sometable
)
INSERT INTO @TOP10
SELECT Value1,Value2,Value3,Value4
FROM
(select
Value1, Value1, Value3, Value4
from BaseTable BT, myCTE MC
where BT.SomeVariable = MC.SomeVariable)
_
どちらも正常に動作し、CTEバージョンでは大幅に少ない時間で同じ結果が返されることがわかります。しかし、上位10個の値を持つというロジックはうまくいかず、20個の値を返すことになっている10個の値のみを返します。
_SET @mycurse = CURSOR FOR
SELECT value FROM sometable
OPEN @mycurse
FETCH NEXT FROM @mycurse INTO @SomeVariable
IF @@FETCH_STATUS <> 0
Print 'Error in the Cursor Fetch Statement'
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @TOP10
SELECT top 10 Value1,Value2,Value3,Value4
FROM
(select
Value1, Value1, Value3, Value4
from BaseTable
where SomeVariable = @SomeVariable)
FETCH NEXT FROM @CUR_Liability INTO @VarLiability
END
CLOSE @CUR_Liability
_
したがって、このシナリオの解決策を提供してください。必ずしもCTEベースである必要はありません。私の目標は実行時間を短縮することです。また、これが十分に明確でない場合は、サンプル結果セットで更新できます。前もって感謝します。
pdate:Row_Number()
関数を使用してソリューションを作成することができましたが、他のオプションについてはまだ興味があります。
私が正しく理解していて、カーソル(またはcte)の反復ごとに2番目のテーブルの10個の値を挿入したい場合は、これを使用できます。
_; WITH myCTE (value) AS
( SELECT value FROM sometable )
INSERT INTO @TOP10
SELECT t.Value1, t.Value2, t.Value3, t.Value4
FROM myCTE AS mc
CROSS APPLY
( SELECT TOP (10)
bt.Value1, bt.Value2, bt.Value3, bt.Value4
FROM BaseTable AS bt
WHERE bt.SomeVariable = mc.value
ORDER BY <SomeColumns> -- needs something here
) AS t ;
_
また、一貫性を保つために、TOP
を含むサブクエリに_ORDER BY
_が必要です。 _order by
_がない場合、データベースエンジンは条件に一致する10行を自由に返すことができます。
ROW_NUMBER()
を使用して行うこともできます。
_; WITH myCTE (Value1, Value2, Value3, Value4) AS
( SELECT bt.Value1, bt.Value2, bt.Value3, bt.Value4,
Rn = ROW_NUMBER() OVER (PARTITION BY bt.SomeVariable
ORDER BY <SomeColumns>)
FROM sometable AS s
JOIN BaseTable AS bt
ON bt.SomeVariable = s.value
)
INSERT INTO @TOP10
SELECT Value1, Value2, Value3, Value4
FROM myCTE
WHERE Rn <= 10 ;
_