これは、以前の質問SQL Server でアイテムの組み合わせを生成する効率的な方法は何ですか?の続きです。私が探しているものとその理由として、実際のシナリオを説明しましょう....
以下のようなテーブルがあるとします
Declare @t table(Number Int)
Insert Into @t Values(10),(20),(30),(40),(18)
Number
10
20
30
40
18
35 (または最も近い) という数字を探す必要があります。
Declare @NumberToLookfor = 35
これで、2 つのペアの組み合わせの重みに基づいて検索が行われます。説明させてください。
10+20 = 30
10+30 = 40
10+40 = 50
10+18 = 28
20 + 30 = 50
20 + 40 = 60
20 + 18 = 38
30 + 40 = 70
30 + 18 = 48
40 + 18 = 58
したがって、任意の 2 つの数値の重みが候補であることがわかります (例: (10,20)、(10,30)...(40,18))。
この場合、最初の 3 つの最も近いペアは (20,18)、(10,20)、(10,30) になります。35 と 38 (20+18) の間のダータンスは 3 であるため、他のペア (10,20) と (10,30) では 5 です。
私が探しているものを理解するための説明は明確だと思います.(そうでない場合はお知らせください)
そうする最も効率的な方法は何ですか?
私の試み
Declare @t table(Number Int)
Insert Into @t Values(10),(20),(30),(40),(18)
;WITH Cte1 (Number,Ids,TotalWeight) AS
(
SELECT Number
, ',' + CAST(Number AS VARCHAR(MAX))
,CAST(Number AS INT)
FROM @t
UNION ALL
SELECT p.Number
,c.Ids + ',' + CAST(p.Number AS VARCHAR(MAX))
,CAST(c.TotalWeight + p.Number AS INT)
FROM @t AS p JOIN Cte1 c ON p.Number < c.Number
),Cte2 AS(
SELECT
*
,DENSE_RANK() OVER(ORDER BY ABS(TotalWeight - 35)) [rank]
FROM Cte1
WHERE (LEN(Ids) - LEN(REPLACE(Ids, ',', '')))/LEN(',') = 2
)
select *
from Cte2 where [rank] <= 2
できます。
しかし、値が非常に大きくなり、たとえば 50 以上になると、効率が非常に悪くなります。最初の CTE では完全な順列を見つけ、2 番目の CTE では 2 つの要素のみが関与する値を選択しているためです。
そのため、値が大きくなると、最初の Cte は非常にゆっくりと動作します。
大きなテーブルの場合でも、他の方法はありますか?
提供される DDL
Declare @t table(Number Int)
Insert Into @t Values
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),
(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),(40),
(41),(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),(57),(58),(59),(60),
(61),(62),(63),(64),(65),(66),(67),(68),(69),(70),(71),(72),(73),(74),(75),(76),(77),(78),(79),(80),
(81),(82),(83),(84),(85),(86),(87),(88),(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99),(100)
よろしくお願いします