Cara PIVOT data dari MSSQL query dan Fetch to PHP view

Dec 04 2020

Saya memiliki Database MSSQL 2005 dengan konten kueri seperti ini:

nopas kode nama memesan
00115301 D031 ADAM 1
00130015 D031 ADAM 2
00149998 D026 JAMES 1
00149970 D028 FIKI 1
00142641 D028 FIKI 2
00127700 D028 FIKI 3

Untuk alasan laporan, saya membutuhkan Output tabel seperti:

ADAM JAMES FIKI ... (catatan baru berbasis konten dinamis)
00115301 00149998 00149970 ...
00130015 - 00142641 ...
- - 00127700 ...

Ada yang bisa bantu saya??

Jawaban

Jason Dec 04 2020 at 16:46

Anda dapat melakukan poros dengan CASEpernyataan. Ini pada dasarnya adalah cara manual untuk melakukan pivot dan jika Anda menggunakan versi SQL Server sebelum 2005, Anda harus mengikuti rute itu. SQL Server 2005 menambahkan fungsi PIVOT .

Karena Anda membutuhkannya untuk menjadi dinamis, Anda perlu menggunakan SQL dinamis . Ini banyak pekerjaan kaki tetapi pasti bisa dilakukan.

Saya akan membuat konten tabel Anda dalam tabel sementara global (harus global untuk bekerja dalam SQL dinamis).

-- 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);

Selanjutnya, saya SELECThanya akan memasukkan nama unik ke dalam tabel sementara lainnya dan mengaitkannya IDENTITYdengan yang dapat saya lakukan iterasi dalam for loop.

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

Sekarang sampai pada bagian yang sulit. The PRINT @dynSQLmenghasilkan apa yang saya coba untuk mencapai dinamis (bawah). Kita perlu SELECTdengan [order], [name], dan [nopas]untuk hasil akhir. Kami berputar [name]di bagian kedua dari pernyataan, dan menggabungkannya dengan MAX([nopas]); tetapi karena kami berisi [order]pengelompokan dalam konten tabel asli Anda, itu hanya akan mengambil MAX([nopas])berdasarkan MAXnilai dari satu baris. Jadi, hasilnya adalah menghilangkan agregasi. Jika Anda tidak memiliki [order]kolom dalam konten asli Anda, kami akan perlu menggunakan fungsi ROW_NUMBER () * PARTITIONED BYyang [name]untuk menghasilkan yang [order].

EDIT: Saya menemukan bahwa ROW_NUMBER()fungsi ini hanya tersedia di SQL Server 2012 dan yang lebih baru.

-- 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;

Oh, jika Anda ingin menghapus [order]kolom, dari hasil. Anda dapat menggunakan SELECT * INTO ##newGlobalTableSQL dinamis dan kemudian ALTERtabel dan DROPkolom baru.