6

2 番目の列の値に基づいて、各行を 1 つ以上の行に分割しようとしているテーブルがあります。このような:

table (id, pcs):
ABC   3
DEF   1
GHJ   4

query result (id, pcs_num):
ABC   1
ABC   2
ABC   3
DEF   1
GHJ   1
GHJ   2
GHJ   3
GHJ   4

私はこれを SQL Server 2008 の sproc として書いています。私の最善の解決策は、カーソルを使用して、テーブルの各行の一時テーブルに [pcs] 行数を追加することです。私が見逃しているのは、これよりも簡単な解決策があるに違いないようです。ありがとう。

4

3 に答える 3

7

再帰的な CTE を使用できます。

;WITH CTE AS
(
    SELECT *
    FROM YourTable
    UNION ALL 
    SELECT id, pcs-1
    FROM CTE
    WHERE pcs-1 >= 1
)
SELECT *
FROM CTE
ORDER BY id, pcs
OPTION(MAXRECURSION 0)

ここにあなたが試すためのデモがあります。

于 2012-11-14T19:15:31.623 に答える
0
SELECT
  id
 ,pcs_num
FROM MyTable
CROSS APPLY (
  SELECT TOP (pcs)
    ROW_NUMBER() OVER(ORDER BY (SELECT 1)) pcs_num
  FROM master.dbo.spt_values
) t
于 2014-09-18T17:32:01.983 に答える
0

これが私のアプローチです。集計表 (値が 1 -> X の列のみを持つ表) を使用すると非常に簡単です。再帰は必要ありません。これにより、大きなテーブルよりもはるかに高速になります。

ここでは 100 行の集計表のみを作成していることに注意してください。お好きなだけ拡大してください。あまりにもクレイジーな場合は、対応するために sys.sysobjects で別のクロス結合が必要になる場合があります。ご覧のように、実際のクエリは一番下にあります。非常に簡単です。

SELECT TOP 100
        IDENTITY( INT,1,1 ) AS N 
 INTO #Tally
FROM    sys.sysobjects sc1 ,

        sys.sysobjects  sc2

CREATE TABLE #Test
(
    Id char(3),
    pcs int
)

INSERT INTO #Test
SELECT 'ABC', 3 UNION ALL
SELECT 'DEF', 1 UNION ALL
SELECT 'GHJ', 4

SELECT #Test.Id, #Tally.N FROM #Tally
    JOIN #Test ON #Tally.N <= #Test.pcs
    ORDER BY #Test.Id
于 2012-11-14T19:20:46.373 に答える