PostgreSQL: WITH 절을 사용하여 문제를 분해하는 예

다음은 WITH 절(일명 CTE - Common Table Expressions)을 사용하여 문제를 분해하는 간단한 예입니다. YugabyteDB 포럼의 질문은 다음과 같은 테이블에 호텔 객실 예약을 저장하는 것에 관한 것입니다.


create table Rooms (PK int primary key, name text, roomNo int);

create table BookedRooms (PK int primary key
, checkInDate timestamptz, checkOutDate timestamptz
, roomId int references Rooms(PK))
;

insert into Rooms values (2,'Deluxe',102),(3,'King',103);
insert into BookedRooms values (1,'2022-05-26T00:00:00Z','2022-05-29T00:00:00Z',2),(2,'2022-05-29T00:00:00Z','2022-05-30T00:00:00Z',3);




내 제안은 다음 쿼리였습니다.

with 
input_month as (
 select 4 as month --> the input months (can be a parameter in a prepared statement)
),
day_generator as (
select 
 date_trunc('year', now())      --> I guess you query for the current year
 + m.month * interval '1 month' --> first day of the month
 + n * interval '1 day'         --> adding 31 days to cover any month
 as day
 from input_month m , generate_series(0,31) n
),
days_of_month as (
select *
from input_month m, day_generator d
 where d.day <                  --> removes the days in next month
 date_trunc('year', now())  + (m.month + 1) * interval '1 month' 
),
result as (
select distinct d.day, r.roomNo 
from days_of_month d, BookedRooms b join Rooms r on (b.roomId=r.PK)
where not(d.day between b.checkInDate and b.checkOutDate) --> remove non available rooms
order by day, roomno
) 
select * from result



입력 매개변수를 input_month 로 정의하는 것으로 시작합니다. 매개변수로 전달할 수 있지만 여러 위치에서 $1를 참조하는 것보다 쿼리 시작 부분의 한 위치에서만 사용하는 것이 더 읽기 쉽습니다.

그런 다음 한 달 동안 모든 날짜를 생성해야 하며 두 단계로 수행합니다. day_geneatorinput_month에서 시작하여 최대값(월 31일)을 생성합니다. 그리고 days_of_month 필터를 사용하여 월의 일수만 가져옵니다(31일 미만인 달).

마지막으로 쿼리는 날짜와 예약 간의 데카르트 조인이며 날짜 간격을 필터링하여 사용 가능한 항목만 표시합니다. 겹치는 부분이 있을 경우를 대비하여 DISTINCT를 추가했지만 이런 일이 발생해서는 안 되며 제약 조건으로 확인해야 합니다. 이것은 다음 블로그 게시물의 주제가 될 수 있습니다.

최종 쿼리는 result에 넣어 주 선택이 가장 간단한 것이 되도록 하여 각 단계를 선택하여 디버그하기 쉽게 합니다.

CTE로 분해하면 다음과 같은 많은 이점이 있습니다.
  • 각 단계를 더 쉽게 읽고 주석을 달 수 있음
  • 쿼리 플래너에서 처리하기 쉬움(각 쿼리 블록을 구체화하거나 구체화하지 않을 수 있음)
  • 최종 선택을 변경하기만 하면 테스트가 더 쉬워짐
    대규모 SQL 쿼리가 잘 설계되어 있는 한 두려워하지 마십시오. 작은 단계로 문제를 해결하기 위해 Linux 명령을 차례로 파이핑하는 것과 같이 생각할 수 있습니다.
  • 좋은 웹페이지 즐겨찾기