2009-11-04 4 views
1

너무 복잡하다? 나는 이것이 훨씬 더 잘 쓰여질 수있다, 나는 당신이 더 많은 쿼리를 사용하여 '레코드 세트를 통해 반복 할 수있다'는 말을 들었다 - 이것이 좋은 일이 될 것인가? 그렇다면 누군가 나를 올바른 방향으로 향하게 할 수 있습니까? 이 쿼리는 3 개의 테이블이있는 하위 쿼리를 포함하여 8 개의 테이블에 분산되어 있으므로 많은 메모리를 사용해야합니다.MySQL의 쿼리 내가이 만든 쿼리를 가지고 있지만이 문제를 가지고

주 - 읽기 전용 액세스 권한이있는 슬레이브 데이터베이스를 사용하므로 구조 변경/테이블 생성 등이 불가능합니다!

도움을 주셔서 감사합니다. 대단히 감사합니다.

Select travel_booking.reference As REF, 
    travel_group.name As `Group Name`, 
    site_user.firstname As `First Name`, 
    site_user.lastname As `Last Name`, 
    site_user.gender, 
    travel_package.start_date As `Start Date`, 
    travel_booking_option.name As `Option Name`, 
    travel_booking_option.text_box_text As `Free Text`, 
    travel_booking_option.select_box_option As `Select Text`, 
    travel_booking_option.option_price As `Option Price`, 
    content.name As `Option Type` 
    From travel_booking Inner Join 
    travel_booking_option On travel_booking_option.travel_bookingid = 
    travel_booking.travel_bookingid Inner Join 
    travel_group On travel_group.travel_groupid = travel_booking.travel_groupid 
Inner Join 
    site_user On site_user.site_userid = travel_booking.site_userid Inner Join 
    travel_option_group On travel_option_group.travel_option_groupid = 
    travel_booking_option.travel_option_groupid Inner Join 
    content On travel_option_group.travel_option_type_content_realid = 
    content.content_realid Inner Join 
    travel_package On travel_package.content_realid = 
    travel_booking.travel_packageid 

Where travel_booking_option.fee = 0 And travel_booking_option.refund = 0 And 
    travel_booking_option.cancel = 0 And travel_booking.cancel = 0 And 
    travel_package.live = 1 And content.live = 1 

Group By travel_booking.reference, 
    travel_group.name, 
    site_user.firstname, 
    site_user.lastname, 
    site_user.gender, 
    travel_package.start_date, 
    travel_booking_option.name, 
    travel_booking_option.text_box_text, 
    travel_booking_option.select_box_option, 
    travel_booking_option.option_price, 
    content.name 
+0

외에도 꽤 좋은 보인다. 인덱스를 조정하여 가능한 한 효율적인지 확인하는 것이 좋습니다. – ChaosPandion

+0

쿼리가 깨끗하고 직관적으로 보입니다 – Xinus

답변

4

비효율적인지 여부를 확인하려면 쿼리의 실행 계획을 검토해야합니다. 실행 중에 적절한 인덱스가 사용된다면 괜찮을 것입니다.

더 많은 쿼리를 사용하여 "루프 스루 레코드 세트"에 대해 질문합니다. 그것은 RBAR (row-by-agonizing-row) 방식이며 가장 권장하지 않습니다. 다음과 같이

나는 더 읽을 수 있도록 쿼리를 다시 포맷 것이다 : 나는 또한 테이블 이름에 별칭을 사용

Select 
    travel_booking.reference As REF, 
    travel_group.name As `Group Name`, 
    site_user.firstname As `First Name`, 
    site_user.lastname As `Last Name`, 
    site_user.gender, 
    travel_package.start_date As `Start Date`, 
    travel_booking_option.name As `Option Name`, 
    travel_booking_option.text_box_text As `Free Text`, 
    travel_booking_option.select_box_option As `Select Text`, 
    travel_booking_option.option_price As `Option Price`, 
    content.name As `Option Type` 

From travel_booking 
    Inner Join travel_booking_option 
     On travel_booking_option.travel_bookingid = travel_booking.travel_bookingid 
    Inner Join travel_group 
     On travel_group.travel_groupid = travel_booking.travel_groupid 
    Inner Join site_user 
     On site_user.site_userid = travel_booking.site_userid 
    Inner Join travel_option_group 
     On travel_option_group.travel_option_groupid = travel_booking_option.travel_option_groupid 
    Inner Join content 
     On travel_option_group.travel_option_type_content_realid = content.content_realid 
    Inner Join travel_package 
     On travel_package.content_realid = travel_booking.travel_packageid 

Where 1=1 
    And travel_booking_option.fee = 0 
    And travel_booking_option.refund = 0 
    And travel_booking_option.cancel = 0 
    And travel_booking.cancel = 0 
    And travel_package.live = 1 
    And content.live = 1 

Group By 
    travel_booking.reference, 
    travel_group.name, 
    site_user.firstname, 
    site_user.lastname, 
    site_user.gender, 
    travel_package.start_date, 
    travel_booking_option.name, 
    travel_booking_option.text_box_text, 
    travel_booking_option.select_box_option, 
    travel_booking_option.option_price, 
    content.name 

.

+0

+1 - 테이블의 별칭을 지정하면 On 절을 다시 끌어 와서 조인을 한 줄로 정리할 수 있습니다. – ChaosPandion

+0

어이 .. 뭐하는거야? 1 = 1 뭐하는거야? – Xinus

+0

나는 실제 where 절이 훌륭하게 정렬되어 있다고 생각한다. – ChaosPandion

2

결과 집합의 모든 열을 GROUP BY하는 것처럼 보이지만 열을 집계하지 않는 것처럼 보입니다. 그렇다면 마지막에 GROUP BY를 제거하고 대신 SELECT 뒤에 DISTINCT라는 단어를 삽입하여 단순화 할 수 있습니다.

또한 테이블 별칭을 사용하여 쿼리를 줄이거 나 (실제로는 단순화 할 수도 있음) 예를 들어 FROM travel_bookingFROM travel_booking TB으로 변경하면 검색어 전체에서 travel_booking. 대신 TB.을 사용할 수 있습니다. 다른 테이블과 유사하게 (물론 각 테이블마다 다른 별칭을 사용하십시오).

마지막으로 응용 프로그램이 열 별칭을 사용하여 자동으로 UI를 작성하지 않을 경우 (예 : 모눈의 열 머리글) 열 별칭도 제거 할 수 있습니다.

그렇지 않으면 쿼리가 매우 단순 해 보입니다. 사람들은 때때로 쿼리에 여러 개의 JOIN이있을 때 어떤 것이 잘못되었다고 걱정하지만 사실은 데이터베이스가 잘 구성되어 있다는 신호 일 가능성이 큽니다. 는 SQL의

내 버전 (열 별칭 포함) : 가난이 쿼리를 포맷하는

SELECT DISTINCT TB.reference As REF, TG.name As `Group Name`, 
    SU.firstname As `First Name`, SU.lastname As `Last Name`, SU.gender, 
    TP.start_date As `Start Date`, 
    TBO.name As `Option Name`, TBO.text_box_text As `Free Text`, TBO.select_box_option As `Select Text`, TBO.option_price As `Option Price`, 
    C.name As `Option Type` 
FROM travel_booking TB 
    Inner Join travel_booking_option TBO On TBO.travel_bookingid = TB.travel_bookingid 
    Inner Join travel_group TG On TG.travel_groupid = TB.travel_groupid 
    Inner Join site_user SU On SU.site_userid = TB.site_userid 
    Inner Join travel_option_group TOG On TOG.travel_option_groupid = TBO.travel_option_groupid 
    Inner Join content C On TOG.travel_option_type_content_realid = C.content_realid 
    Inner Join travel_package TP On TP.content_realid = TB.travel_packageid 
WHERE TBO.fee = 0 And TBO.refund = 0 And TBO.cancel = 0 
    And TB.cancel = 0 And TP.live = 1 And C.live = 1 
관련 문제