PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Bagaimana cara mengembalikan hanya waktu kerja dari reservasi di PostgreSql?

Anda dapat menggunakan fungsi generate_series() untuk menutupi jam di luar jam kerja:

with gaps as (
    select
        upper(during) as start,
        lead(lower(during),1,upper(during)) over (ORDER BY during) - upper(during) as gap
    from (
        select during
        from reservation
        union all
        select
            unnest(case
                when pyha is not null then array[tsrange(d, d + interval '1 day')]
                when date_part('dow', d) in (0, 6) then array[tsrange(d, d + interval '1 day')]
                when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
                else array[tsrange(d, d + interval '8 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
            end)
        from generate_series(
            '2012-11-14'::timestamp without time zone, 
            '2012-11-14'::timestamp without time zone + interval '2 week', 
            interval '1 day'
        ) as s(d) 
        left join pyha on pyha = d::date
    ) as x 
)
select *
    from gaps
where gap > '0'::interval
order by start

Mari saya jelaskan beberapa bagian yang sulit:

  • Anda tidak perlu memasukkan tanggal untuk hari Sabtu/Minggu ke dalam pyha tabel karena Anda dapat menggunakan date_part('dow', d) fungsi. Gunakan pyha meja untuk hari libur nasional saja. 'dow' masing-masing menghasilkan 0 atau 6 untuk Minggu atau Sabtu.
  • libur nasional dan Sabtu/Minggu dapat direpresentasikan sebagai interval tunggal (0..24). Hari kerja harus diwakili oleh dua interval (0..8) dan (18..24) maka unnest() dan array[]
  • Anda dapat menentukan tanggal dan panjang mulai dalam fungsi generate_series()

Berdasarkan pembaruan Anda pada pertanyaan, saya menambahkan when lainnya ke case :

when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]

Idenya adalah untuk menghasilkan interval yang berbeda untuk tanggal mulai (d::date = '2012-11-14' ):(0..9) dan (18..24)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dapatkan nilai paling umum untuk setiap nilai kolom lain di SQL

  2. Apa yang setara dengan MySQL dari EXPLAIN ANALYZE PostgreSQL?

  3. Kesalahan Heroku PostgreSQL GROUP_BY di aplikasi Rails

  4. PostgreSQL melalui SSH Tunnel

  5. Bagaimana cara menggunakan ALIAS dalam klausa ORDER BY PostgreSQL?