Diberikan tabel hirarkis seperti ini:
CREATE TABLE [dbo].[btree]
(
id INT PRIMARY KEY
, parent_id INT REFERENCES [dbo].[btree] ([id])
, name NVARCHAR(20)
);
Saya ingin mendapatkan seluruh struktur pohon.
Misalnya, menggunakan data ini:
INSERT INTO [btree] VALUES (1, null, '1 Root');
INSERT INTO [btree] VALUES (2, 1, '1.1 Group');
INSERT INTO [btree] VALUES (3, 1, '1.2 Group');
INSERT INTO [btree] VALUES (4, 2, '1.1.1 Group');
INSERT INTO [btree] VALUES (5, 2, '1.1.2 Group');
INSERT INTO [btree] VALUES (6, 3, '1.2.1 Group');
INSERT INTO [btree] VALUES (7, 3, '1.2.2 Group');
INSERT INTO [btree] VALUES (8, 4, '1.1.1.1 Items');
INSERT INTO [btree] VALUES (9, 4, '1.1.1.2 Items');
INSERT INTO [btree] VALUES (10, 5, '1.1.2.1 Items');
INSERT INTO [btree] VALUES (11, 5, '1.1.1.2 Items');
INSERT INTO [btree] VALUES (12, 6, '1.2.1.1 Items');
INSERT INTO [btree] VALUES (13, 6, '1.2.1.2 Items');
INSERT INTO [btree] VALUES (14, 7, '1.2.2.1 Items');
Saya ingin mendapatkan:
+----+-----------+---------------------+
| id | parent_id | description |
+----+-----------+---------------------+
| 1 | NULL | 1 Root |
| 2 | 1 | 1.1 Group |
| 4 | 2 | 1.1.1 Group |
| 8 | 4 | 1.1.1.1 Items |
| 9 | 4 | 1.1.1.2 Items |
| 5 | 2 | 1.1.2 Group |
| 10 | 5 | 1.1.2.1 Items |
| 11 | 5 | 1.1.2.2 Items |
| 3 | 1 | 1.2 Group |
| 6 | 3 | 1.2.1 Group |
| 12 | 6 | 1.2.1.1 Items |
| 13 | 6 | 1.2.1.2 Items |
| 7 | 3 | 1.2.2 Group |
| 14 | 7 | 1.2.2.1 Items |
+----+-----------+---------------------+
Saya mengambil rekaman menggunakan kueri rekursif seperti ini:
;WITH tree AS
(
SELECT c1.id, c1.parent_id, c1.name, [level] = 1
FROM dbo.[btree] c1
WHERE c1.parent_id IS NULL
UNION ALL
SELECT c2.id, c2.parent_id, c2.name, [level] = tree.[level] + 1
FROM dbo.[btree] c2 INNER JOIN tree ON tree.id = c2.parent_id
)
SELECT tree.level, tree.id, parent_id, REPLICATE(' ', tree.level - 1) + tree.name AS description
FROM tree
OPTION (MAXRECURSION 0)
;
Dan ini adalah hasil saat ini:
+----+-----------+---------------------+
| id | parent_id | description |
| 1 | NULL | 1 Root |
| 2 | 1 | 1.1 Group |
| 3 | 1 | 1.2 Group |
| 6 | 3 | 1.2.1 Group |
| 7 | 3 | 1.2.2 Group |
| 14 | 7 | 1.2.2.1 Items |
| 12 | 6 | 1.2.1.1 Items |
| 13 | 6 | 1.2.1.2 Items |
| 4 | 2 | 1.1.1 Group |
| 5 | 2 | 1.1.2 Group |
| 10 | 5 | 1.1.2.1 Items |
| 11 | 5 | 1.1.1.2 Items |
| 8 | 4 | 1.1.1.1 Items |
| 9 | 4 | 1.1.1.2 Items |
+----+-----------+---------------------+
Saya tidak tahu cara memesannya berdasarkan level.
Apakah ada cara untuk menetapkan peringkat untuk setiap sub-level?
Saya sudah menyiapkan Rextester
t-sql
sql-server-2014
hierarchy
McNets
sumber
sumber
c2.id
diganti dengan row_number dan empuk di sebelah kiri sehingga semua bagian memiliki panjang yang sama. Kalau tidak, itu tidak akan berfungsi untuk semua data. Cukup ganti 2 dengan 55 di data dan perubahan pesananPath
dengan koreksi kecil, untuk menambahkan padding.Kecurangan, hanya sedikit;) Lihat bu, jangan rekursi!
Diuji di rextester.com
Tentu saja hal di atas agak terbatas. Ini hanya berfungsi berdasarkan asumsi:
name
kolom telah disimpan (di bagian pertama) sebenarnya "jalan".CAST .. AS int
diperlukan hanya jika bagian-bagian yang nomor.Penjelasan: Kode ini bekerja dengan menggunakan fungsi
PARSENAME()
yang memiliki tujuan utama membagi nama objek menjadi 4 bagian:Perhatikan bahwa urutannya terbalik. Sebagai contoh,
PARSENAME('dbo.btree', 2)
akan memberi kita'dbo'
sebagai hasilnya. Dengan 3, kita akan mendapatkan NULL (itu sebabnyaREVERSE()
digunakan dua kali dalam kode. Kalau tidak kita akan mendapatkan nol di awal.'1.2'
Akan diurai menjadi seperti yangnull, null, 1, 2
kita inginkan1, 2, null, null
. )Kesimpulan: setelah semua itu, saya harus menambahkan bahwa jawaban oleh Bob Campbel adalah cara untuk pergi karena lebih umum dan menghasilkan (dalam kolom "jalan" di hasilnya) hierarki jalur, yang kemudian dapat digunakan untuk
ORDER BY
.Opsi lain yang dapat Anda pertimbangkan - jika ukuran tabel bertambah besar dan solusi rekursif menjadi lambat - adalah untuk benar-benar menyimpan jalur dalam kolom terpisah (dalam format yang baik untuk pemesanan, yaitu dengan bantalan) atau menggunakan yang disediakan
HierarchyID
jenis yang tepat untuk kasus penggunaan ini, data hierarkis.sumber
name
tidak dapat digunakan dalam kasus ini. Butuh waktu sepanjang malam untuk menguraikannya, bisakah saya memiliki penjelasan?name
tidak menyimpan path (dengan teks), seperti'order173.palletA27.box9'.bag3A
, Anda masih bisa menggunakan kode (cukup hapus gips ke int). Bagaimanapun, permintaan oleh BenCambell adalah cara untuk pergi secara umum.