Secara umum, perencana kueri Postgres melakukannya tampilan "inline" untuk mengoptimalkan seluruh kueri. Per dokumentasi:
Tapi saya tidak berpikir Postgres cukup pintar untuk menyimpulkan bahwa itu dapat mencapai hasil yang sama dari tabel dasar tanpa meledakkan baris.
Anda dapat mencoba kueri alternatif ini dengan LATERAL
Ikuti. Lebih bersih:
CREATE OR REPLACE VIEW runinfo.v_mt_count_by_day AS
SELECT m.run_id, m.type, m.brand
, m.start_day + c.rn - 1 AS row_date
, c.row_count
FROM runinfo.mt_count_by_day m
LEFT JOIN LATERAL unnest(m.counts) WITH ORDINALITY c(row_count, rn) ON true;
Ini juga menjelaskan bahwa salah satu dari (end_day
, start_day
) berlebihan.
Menggunakan LEFT JOIN
karena itu mungkin memungkinkan perencana kueri mengabaikan gabungan dari kueri Anda:
SELECT DISTINCT type FROM v_mt_count_by_day;
Lain (dengan CROSS JOIN
atau INNER JOIN
) itu harus mengevaluasi gabungan untuk melihat apakah baris dari tabel pertama dihilangkan.
BTW, ini:
SELECT DISTINCT type ...
bukan:
SELECT DISTINCT(type) ...
Perhatikan bahwa ini mengembalikan date
alih-alih stempel waktu di aslinya. Lebih mudah, dan saya rasa itu yang Anda inginkan?
Membutuhkan Postgres 9.3+ Detail:
ROWS FROM
di Postgres 9.4+
Untuk meledakkan kedua kolom secara paralel dengan aman :
CREATE OR REPLACE VIEW runinfo.v_mt_count_by_day AS
SELECT m.run_id, m.type, m.brand
t.row_date::date, t.row_count
FROM runinfo.mt_count_by_day m
LEFT JOIN LATERAL ROWS FROM (
unnest(m.counts)
, generate_series(m.start_day, m.end_day, interval '1d')
) t(row_count, row_date) ON true;
Manfaat utama:Ini tidak akan keluar dari produk Cartesian jika kedua SRF tidak mengembalikan jumlah baris yang sama. Sebagai gantinya, nilai NULL akan diisi.
Sekali lagi, saya tidak dapat mengatakan apakah ini akan membantu perencana kueri dengan rencana yang lebih cepat untuk DISTINCT type
tanpa pengujian.