Skema yang diajukan
Pertama dan terpenting, berikut adalah contoh skema yang saya usulkan untuk referensi di seluruh posting saya:
Clothes
----------
ClothesID (PK) INT NOT NULL
Name VARCHAR(50) NOT NULL
Color VARCHAR(50) NOT NULL
Price DECIMAL(5,2) NOT NULL
BrandID INT NOT NULL
...
Brand_1
--------
ClothesID (FK/PK) int NOT NULL
ViewingUrl VARCHAR(50) NOT NULL
SomeOtherBrand1SpecificAttr VARCHAR(50) NOT NULL
Brand_2
--------
ClothesID (FK/PK) int NOT NULL
PhotoUrl VARCHAR(50) NOT NULL
SomeOtherBrand2SpecificAttr VARCHAR(50) NOT NULL
Brand_X
--------
ClothesID (FK/PK) int NOT NULL
SomeOtherBrandXSpecificAttr VARCHAR(50) NOT NULL
Pernyataan masalah
Saya memiliki meja pakaian yang memiliki kolom seperti nama, warna, harga, brandid dan sebagainya untuk menggambarkan atribut untuk item pakaian tertentu.
Inilah masalah saya: berbeda merek s pakaian memerlukan informasi yang berbeda. Apa praktik terbaik untuk menangani masalah seperti ini?
Perhatikan bahwa untuk tujuan saya, perlu mencari informasi khusus merek mulai dari entri pakaian . Ini karena saya pertama kali menampilkan informasi dari entri pakaian kepada pengguna, setelah itu saya harus menggunakan informasi khusus mereknya untuk membeli item. Singkatnya, harus ada hubungan terarah antara pakaian (dari) dan tabel brand_x .
Solusi yang diajukan / saat ini
Untuk mengatasinya, saya telah memikirkan skema desain berikut:
The pakaian meja akan memiliki merek kolom yang mungkin memiliki nilai id mulai dari 1 sampai x, di mana tertentu berkoresponden id ke meja merek tertentu. Misalnya, nilai id 1 akan sesuai dengan tabel brand_1 (yang mungkin memiliki kolom url ), id 2 akan sesuai dengan brand_2 (yang mungkin memiliki kolom pemasok ), dll.
Jadi untuk menghubungkan entri pakaian tertentu dengan informasi spesifik mereknya, saya membayangkan logika pada tingkat aplikasi akan terlihat seperti ini:
clothesId = <some value>
brand = query("SELECT brand FROM clothes WHERE id = clothesId")
if (brand == 1) {
// get brand_1 attributes for given clothesId
} else if (brand == 2) {
// get brand_2 attributes for given clothesId
} ... etc.
Komentar & pemikiran lain
Saya mencoba untuk menormalkan seluruh database saya di BCNF, dan meskipun ini yang saya buat, kode aplikasi yang dihasilkan membuat saya merasa sangat cemas. Tidak ada cara untuk menegakkan hubungan kecuali pada tingkat aplikasi, dan dengan demikian desainnya terasa sangat berantakan dan, saya mengantisipasi, sangat rawan kesalahan.
Penelitian
Saya memastikan untuk melihat entri sebelumnya sebelum membuat posting. Berikut adalah pos dengan masalah yang hampir identik yang berhasil saya temukan. Saya tetap membuat posting ini karena sepertinya satu-satunya jawaban yang diberikan tidak memiliki solusi berbasis desain atau SQL (yaitu menyebutkan OOP, warisan, dan antarmuka).
Saya juga seorang pemula dalam hal desain database, jadi saya sangat menghargai wawasan apa pun.
Tampaknya ada respons yang lebih membantu pada Stack Overflow:
- Sini
- Dan di sini
- Aaaand di sini (konsep utama adalah: warisan tabel kelas)
Saya telah merujuk solusi di sana dan menyarankan orang lain menemukan pertanyaan saya juga.
Terlepas dari tautan yang disediakan di atas, saya masih mencari tanggapan di sini dan akan menghargai setiap solusi yang disediakan!
Saya menggunakan PostgreSQL.
sumber
Apa yang Anda gambarkan adalah, setidaknya sebagian, katalog produk. Anda memiliki beberapa atribut yang umum untuk semua produk. Ini termasuk dalam tabel yang dinormalisasi dengan baik.
Di luar itu, Anda memiliki serangkaian atribut yang spesifik merek (dan saya harapkan bisa spesifik produk). Apa yang perlu dilakukan sistem Anda dengan atribut spesifik ini? Apakah Anda memiliki logika bisnis yang bergantung pada skema atribut ini atau Anda hanya mencantumkannya dalam serangkaian pasangan "label": "nilai"?
Jawaban lain menyarankan menggunakan apa yang pada dasarnya pendekatan CSV (apakah ini
JSON
atauARRAY
atau sebaliknya) - ini pendekatan mengorbankan skema relasional biasa menangani dengan memindahkan skema dari metadata dan ke dalam data itu sendiri.Ada pola desain portabel untuk ini yang sangat cocok dengan basis data relasional. Itu adalah EAV (entitas-atribut-nilai). Saya yakin Anda telah membaca di banyak tempat "EAV is Evil" (dan memang demikian). Namun, ada satu aplikasi khusus di mana masalah dengan EAV tidak penting, dan itu adalah katalog atribut produk.
Semua argumen biasa terhadap EAV tidak berlaku untuk katalog fitur produk, karena nilai-nilai fitur produk umumnya hanya dimuntahkan ke dalam daftar atau kasus terburuk ke dalam tabel perbandingan.
Menggunakan
JSON
tipe kolom membutuhkan kemampuan Anda untuk menegakkan batasan data apa pun dari database dan memaksanya ke dalam logika aplikasi Anda. Juga, menggunakan satu tabel atribut untuk setiap merek memiliki kelemahan berikut:Tidak terlalu sulit untuk mengambil data tentang suatu produk dengan fitur-fitur khusus merek. Mungkin lebih mudah untuk membuat SQL dinamis menggunakan model EAV daripada menggunakan model tabel-per-kategori. Dalam tabel-per-kategori, Anda perlu refleksi (atau Anda
JSON
) untuk mencari tahu apa nama kolom fitur. Kemudian Anda bisa membuat daftar item untuk klausa tempat. Dalam model EAV,WHERE X AND Y AND Z
menjadiINNER JOIN X INNER JOIN Y INNER JOIN Z
, jadi kueri sedikit lebih rumit, tetapi logika untuk membangun kueri masih sepenuhnya didorong oleh tabel dan itu akan lebih dari cukup terukur jika Anda memiliki indeks yang tepat dibangun.Ada banyak alasan untuk tidak menggunakan EAV sebagai pendekatan umum. Alasan-alasan itu tidak berlaku untuk katalog fitur produk sehingga tidak ada yang salah dengan EAV dalam aplikasi spesifik ini.
Yang pasti, ini adalah jawaban singkat untuk topik yang kompleks dan kontroversial. Saya telah menjawab pertanyaan serupa sebelumnya dan membahas lebih detail tentang penolakan umum terhadap EAV. Sebagai contoh:
Saya akan mengatakan EAV digunakan lebih jarang akhir-akhir ini daripada dulu, karena sebagian besar alasan bagus. Namun, saya pikir itu juga tidak dipahami dengan baik.
sumber
Menggunakan JSON dan PostgreSQL
Saya pikir Anda membuat ini lebih sulit dari yang seharusnya dan Anda akan digigitnya nanti. Anda tidak perlu model nilai Entitas – atribut-nilai kecuali Anda benar-benar membutuhkan EAV.
Sama sekali tidak ada yang salah dengan skema ini.
Sekarang Anda dapat menanyakannya menggunakan gabungan sederhana
Dan salah satu operator JSON bekerja di mana klausa.
Sebagai catatan tambahan, jangan taruh url di database. Mereka berubah seiring waktu. Cukup buat fungsi yang membawanya.
atau terserah. Jika Anda menggunakan PostgreSQL Anda bahkan dapat menggunakan hashids .
Juga dari catatan khusus,
jsonb
disimpan sebagai biner (dengan demikian -'b ') dan juga dapat diindeks, atau SARGable atau apa pun yang disebut anak-anak keren hari ini:CREATE INDEX ON brands USING gin ( attributes );
Perbedaannya di sini adalah kesederhanaan kueri ..
Bagaimana dengan yang berbeda ..
sumber
Salah satu solusi mudah adalah dengan memasukkan semua atribut yang mungkin sebagai kolom pada tabel pakaian utama, dan membuat semua kolom khusus merek dapat dibatalkan. Solusi ini memecah normalisasi database, tetapi sangat mudah diimplementasikan.
sumber