Pengalaman DBA saya tidak lebih jauh dari penyimpanan sederhana + pengambilan data gaya CMS - jadi ini mungkin pertanyaan konyol, saya tidak tahu!
Saya memiliki masalah di mana saya perlu mencari atau menghitung harga liburan untuk ukuran grup tertentu dan beberapa hari dalam periode waktu tertentu. Misalnya:
Berapa harga kamar hotel untuk 2 orang selama 4 malam kapan saja di bulan Januari?
Saya memiliki data harga dan ketersediaan untuk, katakanlah, 5000 hotel disimpan seperti ini:
Hotel ID | Date | Spaces | Price PP
-----------------------------------
123 | Jan1 | 5 | 100
123 | Jan2 | 7 | 100
123 | Jan3 | 5 | 100
123 | Jan4 | 3 | 100
123 | Jan5 | 5 | 100
123 | Jan6 | 7 | 110
456 | Jan1 | 5 | 120
456 | Jan2 | 1 | 120
456 | Jan3 | 4 | 130
456 | Jan4 | 3 | 110
456 | Jan5 | 5 | 100
456 | Jan6 | 7 | 90
Dengan tabel ini, saya dapat melakukan kueri seperti ini:
SELECT hotel_id, sum(price_pp)
FROM hotel_data
WHERE
date >= Jan1 and date <= Jan4
and spaces >= 2
GROUP BY hotel_id
HAVING count(*) = 4;
hasil
hotel_id | sum
----------------
123 | 400
The HAVING
klausul sini membuat yakin bahwa ada sebuah entri untuk setiap hari antara tanggal yang diinginkan saya yang memiliki ruang yang tersedia. yaitu. Hotel 456 memiliki 1 ruang yang tersedia pada Jan2, klausa HAVING akan mengembalikan 3, jadi kami tidak mendapatkan hasil untuk hotel 456.
Sejauh ini bagus.
Namun, apakah ada cara untuk mengetahui semua periode 4 malam di bulan Januari di mana ada ruang yang tersedia? Kami dapat mengulangi kueri 27 kali - menambah tanggal setiap kali, yang sepertinya sedikit canggung. Atau cara lain untuk menyimpan semua kemungkinan kombinasi dalam tabel pencarian seperti:
Hotel ID | total price pp | num_people | num_nights | start_date
----------------------------------------------------------------
123 | 400 | 2 | 4 | Jan1
123 | 400 | 2 | 4 | Jan2
123 | 400 | 2 | 4 | Jan3
123 | 400 | 3 | 4 | Jan1
123 | 400 | 3 | 4 | Jan2
123 | 400 | 3 | 4 | Jan3
Dan seterusnya. Kami harus membatasi jumlah maksimum malam, dan jumlah maksimum orang yang akan kami cari - mis. Maks malam = 28, maks orang = 10 (terbatas pada jumlah ruang yang tersedia untuk periode yang ditetapkan yang dimulai pada tanggal itu).
Untuk satu hotel, ini bisa memberi kita 28 * 10 * 365 = 102000 hasil per tahun. 5000 hotel = hasil 500 juta!
Tapi kami akan memiliki pertanyaan yang sangat sederhana untuk menemukan menginap 4 malam termurah di Jan untuk 2 orang:
SELECT
hotel_id, start_date, price
from hotel_lookup
where num_people=2
and num_nights=4
and start_date >= Jan1
and start_date <= Jan27
order by price
limit 1;
Apakah ada cara untuk melakukan kueri ini di tabel awal tanpa harus membuat tabel pencarian 500m baris !? misalnya menghasilkan 27 hasil yang mungkin dalam tabel sementara atau beberapa sihir permintaan dalam lainnya?
Saat ini semua data disimpan dalam Postgres DB - jika perlu untuk tujuan ini kita dapat memindahkan data ke hal lain yang lebih cocok? Tidak yakin apakah jenis kueri ini cocok dengan peta / kurangi pola untuk DB gaya NoSQL ...
sumber
Cara lain, menggunakan
LAG()
fungsi:Tes di: SQL-Fiddle
sumber
(spaces, day)
, bahkan mungkin indeks penutup aktif(spaces, day, hotel_id, price)
.seharusnya memberi Anda hasil yang Anda cari tanpa memerlukan struktur tambahan, meskipun tergantung pada ukuran data input, struktur indeks Anda, dan seberapa cerah perencana kueri adalah permintaan dalam dapat menghasilkan spool ke disk. Anda mungkin menemukannya cukup efisien. Peringatan: keahlian saya adalah dengan MS SQL Server dan kemampuan perencana kuasanya ,
jadi sintaks di atas mungkin perlu tweeks jika hanya dalam nama fungsi(ypercube telah menyesuaikan sintaks sehingga mungkin postgres kompatibel sekarang, lihat riwayat jawaban untuk varian TSQL) .Hal di atas akan menemukan masa inap yang dimulai pada bulan Januari tetapi berlanjut hingga Februari. Menambahkan klausa tambahan ke pengujian tanggal (atau menyesuaikan nilai tanggal akhir yang masuk) akan dengan mudah mengatasinya jika tidak diinginkan.
sumber
Terlepas dari HotelID, Anda bisa menggunakan tabel penjumlahan, dengan kolom terhitung, seperti:
Tidak ada Kunci Utama atau Asing dalam tabel ini, karena ini hanya digunakan untuk dengan cepat menghitung beberapa kombinasi Nilai. Jika Anda membutuhkan atau menginginkan lebih dari satu nilai yang dihitung, buat tampilan baru dengan nama tampilan baru untuk setiap nilai bulan dalam kombinasi dengan masing-masing Nilai People dan PP Nilai:
CONTOH KODE PSEUDO
SummedColumn = 2400
Terakhir, Gabung View ke HotelID. Untuk melakukan itu, Anda perlu Menyimpan daftar semua HotelID di SummingTable (Saya Lakukan di Tabel Di Atas), meskipun HotelID tidak digunakan untuk menghitung dalam Tampilan. Seperti begitu:
LEBIH BANYAK KODE PSEUDO
sumber