MSSQLクエリからデータをピボットしてPHPビューにフェッチする方法

Dec 04 2020

次のようなクエリコンテンツを含むMSSQL2005データベースがあります。

nopas コード 名前 注文
00115301 D031 アダム 1
00130015 D031 アダム 2
00149998 D026 ジェームズ 1
00149970 D028 FIKI 1
00142641 D028 FIKI 2
00127700 D028 FIKI 3

レポートの理由から、次のようなテーブルを出力する必要があります。

アダム ジェームズ FIKI ...(動的コンテンツベースの新しいレコード)
00115301 00149998 00149970 ..。
00130015 - 00142641 ..。
- - 00127700 ..。

誰か助けてもらえますか?

回答

Jason Dec 04 2020 at 16:46

CASEステートメントを使用してピボットを実行できます。これは基本的に手動でピボットする方法であり、2005年より前のバージョンのSQL Serverを使用していた場合は、そのルートを使用する必要があります。SQL Server 2005では、PIVOT関数が追加されました。

動的である必要があるため、動的SQLを使用する必要があります。それは多くの脚の仕事ですが、間違いなく実行可能です。

グローバル一時テーブルにテーブルコンテンツを作成します(動的SQLで機能するにはグローバルである必要があります)。

-- CREATE GLOBAL TEMPORARY TABLE
CREATE TABLE ##tablename (
  [nopas] VARCHAR(8),
  [code] VARCHAR(4),
  [name] VARCHAR(64),
  [order] SMALLINT
);

INSERT INTO ##tablename
  ([nopas], [code], [name], [order])
VALUES
 ('00115301','D031','ADAM',  1)
,('00130015','D031','ADAM',  2)
,('00149998','D026','JAMES', 1)
,('00149970','D028','FIKI',  1)
,('00142641','D028','FIKI',  2)
,('00127700','D028','FIKI',  3);

次に、SELECT一意の名前だけを別の一時テーブルIDENTITYに入れて、forループで繰り返すことができると関連付けます。

SELECT IDENTITY(INT, 1,1) as [id], [name] 
INTO #temp
FROM ##tablename
GROUP BY [name];

今、難しい部分が来ます。はPRINT @dynSQL、動的に達成しようとしていることを生成します(以下)。我々はする必要があり、および最終的な結果のために。ステートメントの2番目の部分でピボットし、;で集計します。ただし、元のテーブルコンテンツにはグループ化が含まれているため、単一の行の値に基づいてのみ取得されます。したがって、結果として、集約が削除されます。あなたが持っていなかった場合は、あなたのオリジナルコンテンツで列を、我々は、使用する必要がありますROW_NUMBER()関数を*それを生成します。SELECT[order][name][nopas][name]MAX([nopas])[order]MAX([nopas])MAX[order]PARTITIONED BY[name][order]

編集:このROW_NUMBER()関数はSQL Server2012以降でのみ使用できることを発見しました。

-- PRINT @dynSQL result
SELECT * FROM
(SELECT [order], [name], [nopas]
  FROM ##tablename) AS sourceTable
PIVOT(
MAX([nopas])
FOR [name] IN ([ADAM],[FIKI],[JAMES])
) AS pivotTable;
-- The leg work to create the dynamic SQL.
DECLARE @count INT = 1;
DECLARE @max INT = (SELECT MAX(id) FROM #temp);
DECLARE @dynSQL VARCHAR(2048) = 'SELECT * FROM
(SELECT [order], [name], [nopas]
  FROM ##tablename) AS sourceTable
PIVOT(
MAX([nopas])
FOR [name] IN (';

SET @count = 1;
WHILE(@count <= @max)
BEGIN
  SET @dynSQL += '[' + (SELECT [name] FROM #temp WHERE id = @count) + '],';
  SET @count += 1;
END

SET @dynSQL = LEFT(@dynSQL, DATALENGTH(@dynSQL) -1) + ')
) AS pivotTable;';

PRINT @dynSQL;
EXEC (@dynSQL);

DROP TABLE ##tablename;
DROP TABLE #temp;

ああ、[order]結果から列を削除したい場合。SELECT * INTO ##newGlobalTable動的SQLで使用してからALTER、新しいテーブルとDROP列で使用できます。