2009-11-04 4 views
1

J'ai une requête que je l'ai fait, mais j'ai un problème avec -MySQL Query est beaucoup trop compliqué

Est-ce la façon de « neatest » d'écrire cela? Je pense que cela pourrait être écrit beaucoup mieux, j'ai entendu dire que vous pouvez «boucler le jeu d'enregistrements» en utilisant plus de requêtes - serait-ce une bonne chose à faire? Et si oui, quelqu'un peut-il me diriger dans la bonne direction? Cette requête doit utiliser beaucoup de mémoire car elle est répartie sur 8 tables incluant une sous-requête avec 3 tables.

Remarque - J'utilise une base de données esclave avec un accès en lecture seule, il est donc impossible de changer de structure/créer des tables, etc.

Un grand merci pour toute aide. Très apprécié.

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

En plus d'être mal formaté cette requête semble assez agréable. Pourquoi ne modifiez-vous pas simplement vos index pour vous assurer qu'ils sont aussi efficaces que possible. – ChaosPandion

+0

La requête me semble propre et directe – Xinus

Répondre

4

Vous devez revoir le plan d'exécution de la requête pour voir si elle est inefficace ou non. Tant que les indices appropriés sont utilisés pendant l'exécution, tout devrait bien se passer.

Vous vous posez des questions sur "'loop through recordset' en utilisant plus de requêtes". C'est une approche RBAR (row-by-agonizing-row) et n'est certainement pas recommandé.

je serais reformater la requête pour le rendre plus lisible comme suit:

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 

Je également utiliser des alias pour les noms de table.

+0

+1 - S'ils alias les tables, ils peuvent sauvegarder la clause On pour que les jointures soient belles et propres sur une ligne. – ChaosPandion

+0

hey .. qu'est-ce que 1 = 1 faire là? – Xinus

+0

Je pense que c'est ainsi que la clause where réelle s'aligne bien. – ChaosPandion

2

Il me semble que vous groupez BY chaque colonne dans votre jeu de résultats mais pas agréger les colonnes. Si c'est le cas, vous pouvez simplifier en supprimant le GROUP BY à la fin et en insérant le mot DISTINCT après SELECT.

Vous pouvez également raccourcir (mais pas réellement simplifier) ​​la requête en utilisant des alias de table. Par exemple, si vous changez FROM travel_booking en FROM travel_booking TB, vous pouvez alors utiliser TB. à la place de travel_booking. tout au long de la requête. De même avec d'autres tables (utilisez un alias différent pour chaque table, bien sûr). Enfin, si votre application n'utilise pas les alias de colonnes pour créer l'interface utilisateur automatiquement (par exemple, pour les en-têtes de colonne dans une grille), vous pouvez également supprimer les alias de colonnes.

Sinon, la requête semble assez simple. Les gens s'inquiètent parfois que quelque chose ne va pas lorsqu'ils ont plusieurs JOINs dans leur requête mais, en fait, c'est plus susceptible d'être un signe que la base de données est bien structurée.

Ma version de SQL (alias de colonne inclus):

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