我正在运行一个相当复杂(并且非常难看)的查询作为管理搜索页面的一部分。它按预期工作,直到搜索参数包含a。在它,例如。 foo@bar.com打破它,foo @ bar没有。查询构建如下:
DealPurchase.order('created_at DESC').includes(
:couple => :couple_detail, :vendor => :vendor_detail
).joins(:couple => :couple_detail).joins(:vendor => :vendor_detail).joins(
"LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id"
).where(
"CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE ? OR " +
"vendor_detail.business_name LIKE ? OR " +
"users.email LIKE ? OR " +
"coupons.coupon_code LIKE ? OR " +
"deal_purchases.voucher_code LIKE ?",
"%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%"
).includes(:coupon)
当生成的查询有效时,它看起来像:
SELECT `deal_purchases`.* FROM `deal_purchases` INNER JOIN `users` ON `users`.`user_id` = `deal_purchases`.`couple_id` INNER JOIN `couple_detail` ON `couple_detail`.`user_id` = `users`.`user_id` INNER JOIN `users` `vendors_deal_purchases` ON `vendors_deal_purchases`.`user_id` = `deal_purchases`.`vendor_id` INNER JOIN `vendor_detail` ON `vendor_detail`.`user_id` = `vendors_deal_purchases`.`user_id` LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id WHERE (CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE '%keifatosweet@hotmail%' OR vendor_detail.business_name LIKE '%keifatosweet@hotmail%' OR users.email LIKE '%keifatosweet@hotmail%' OR coupons.coupon_code LIKE '%keifatosweet@hotmail%' OR deal_purchases.voucher_code LIKE '%keifatosweet@hotmail%') ORDER BY created_at DESC
当params [:search]包含a。它看起来像:
SELECT `deal_purchases`.`id` AS t0_r0, `deal_purchases`.`couple_id` AS t0_r1, `deal_purchases`.`vendor_id` AS t0_r2, `deal_purchases`.`deal_id` AS t0_r3, `deal_purchases`.`transaction_id` AS t0_r4, `deal_purchases`.`voucher_code` AS t0_r5, `deal_purchases`.`created_at` AS t0_r6, `deal_purchases`.`updated_at` AS t0_r7, `deal_purchases`.`credit_card_id` AS t0_r8, `deal_purchases`.`used` AS t0_r9, `deal_purchases`.`paid` AS t0_r10, `deal_purchases`.`refunded` AS t0_r11, `deal_purchases`.`cents_spent` AS t0_r12, `deal_purchases`.`weddingful_cents_spent` AS t0_r13, `deal_purchases`.`weddingful_cents_awarded` AS t0_r14, `deal_purchases`.`affiliate_id` AS t0_r15, `deal_purchases`.`affiliate_cents` AS t0_r16, `deal_purchases`.`affiliate_link_id` AS t0_r17, `deal_purchases`.`coupon_id` AS t0_r18, `users`.`user_id` AS t1_r0, `users`.`email` AS t1_r1, `users`.`password` AS t1_r2, `users`.`create_date` AS t1_r3, `users`.`last_updated` AS t1_r4, `users`.`last_login` AS t1_r5, `users`.`user_type` AS t1_r6, `users`.`status` AS t1_r7, `users`.`fb_user_id` AS t1_r8, `couple_detail`.`id` AS t2_r0, `couple_detail`.`user_id` AS t2_r1, `couple_detail`.`fname` AS t2_r2, `couple_detail`.`lname` AS t2_r3, `couple_detail`.`fiance_fname` AS t2_r4, `couple_detail`.`fiance_lname` AS t2_r5, `couple_detail`.`phone` AS t2_r6, `couple_detail`.`address1` AS t2_r7, `couple_detail`.`address2` AS t2_r8, `couple_detail`.`city` AS t2_r9, `couple_detail`.`state` AS t2_r10, `couple_detail`.`country` AS t2_r11, `couple_detail`.`zipcode` AS t2_r12, `couple_detail`.`couple_role` AS t2_r13, `couple_detail`.`fiance_role` AS t2_r14, `couple_detail`.`logo` AS t2_r15, `couple_detail`.`status` AS t2_r16, `couple_detail`.`completed_registration` AS t2_r17, `couple_detail`.`weddingful_cents` AS t2_r18, `vendors_deal_purchases`.`user_id` AS t3_r0, `vendors_deal_purchases`.`email` AS t3_r1, `vendors_deal_purchases`.`password` AS t3_r2, `vendors_deal_purchases`.`create_date` AS t3_r3, `vendors_deal_purchases`.`last_updated` AS t3_r4, `vendors_deal_purchases`.`last_login` AS t3_r5, `vendors_deal_purchases`.`user_type` AS t3_r6, `vendors_deal_purchases`.`status` AS t3_r7, `vendors_deal_purchases`.`fb_user_id` AS t3_r8, `vendor_detail`.`id` AS t4_r0, `vendor_detail`.`user_id` AS t4_r1, `vendor_detail`.`business_name` AS t4_r2, `vendor_detail`.`business_phone` AS t4_r3, `vendor_detail`.`first_name` AS t4_r4, `vendor_detail`.`last_name` AS t4_r5, `vendor_detail`.`url` AS t4_r6, `vendor_detail`.`address1` AS t4_r7, `vendor_detail`.`address2` AS t4_r8, `vendor_detail`.`city` AS t4_r9, `vendor_detail`.`state` AS t4_r10, `vendor_detail`.`country` AS t4_r11, `vendor_detail`.`zipcode` AS t4_r12, `vendor_detail`.`business_description` AS t4_r13, `vendor_detail`.`tagline` AS t4_r14, `vendor_detail`.`logo` AS t4_r15, `vendor_detail`.`logo_caption` AS t4_r16, `vendor_detail`.`store_type` AS t4_r17, `vendor_detail`.`vendor_type` AS t4_r18, `vendor_detail`.`signup_pitch_seen` AS t4_r19, `vendor_detail`.`signup_complete` AS t4_r20, `vendor_detail`.`profile_views` AS t4_r21, `vendor_detail`.`hash_key` AS t4_r22, `vendor_detail`.`available_credits` AS t4_r23, `vendor_detail`.`credit_expire_on` AS t4_r24, `vendor_detail`.`promotion_title` AS t4_r25, `vendor_detail`.`promotion_text` AS t4_r26, `vendor_detail`.`promotion_posted_on` AS t4_r27, `vendor_detail`.`notes` AS t4_r28, `vendor_detail`.`last_updated` AS t4_r29, `vendor_detail`.`claim_date` AS t4_r30, `vendor_detail`.`profile_percentage` AS t4_r31, `vendor_detail`.`vendor_url` AS t4_r32, `vendor_detail`.`status` AS t4_r33, `vendor_detail`.`twilio_number` AS t4_r34 FROM `deal_purchases` INNER JOIN `users` ON `users`.`user_id` = `deal_purchases`.`couple_id` INNER JOIN `couple_detail` ON `couple_detail`.`user_id` = `users`.`user_id` INNER JOIN `users` `vendors_deal_purchases` ON `vendors_deal_purchases`.`user_id` = `deal_purchases`.`vendor_id` INNER JOIN `vendor_detail` ON `vendor_detail`.`user_id` = `vendors_deal_purchases`.`user_id` LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id WHERE (CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE '%@hotmail.com%' OR vendor_detail.business_name LIKE '%@hotmail.com%' OR users.email LIKE '%@hotmail.com%' OR coupons.coupon_code LIKE '%@hotmail.com%' OR deal_purchases.voucher_code LIKE '%@hotmail.com%') ORDER BY created_at DESC
产生的错误是:
Mysql2::Error: Not unique table/alias: 'coupons': SELECT `deal_purchases`.`id` AS t0_r0, `deal_purchases`.`couple_id` AS t0_r1, `deal_purchases`.`vendor_id` AS t0_r2, `deal_purchases`.`deal_id` AS t0_r3, `deal_purchases`.`transaction_id` AS t0_r4, `deal_purchases`.`voucher_code` AS t0_r5, `deal_purchases`.`created_at` AS t0_r6, `deal_purchases`.`updated_at` AS t0_r7, `deal_purchases`.`credit_card_id` AS t0_r8, `deal_purchases`.`used` AS t0_r9, `deal_purchases`.`paid` AS t0_r10, `deal_purchases`.`refunded` AS t0_r11, `deal_purchases`.`cents_spent` AS t0_r12, `deal_purchases`.`weddingful_cents_spent` AS t0_r13, `deal_purchases`.`weddingful_cents_awarded` AS t0_r14, `deal_purchases`.`affiliate_id` AS t0_r15, `deal_purchases`.`affiliate_cents` AS t0_r16, `deal_purchases`.`affiliate_link_id` AS t0_r17, `deal_purchases`.`coupon_id` AS t0_r18, `users`.`user_id` AS t1_r0, `users`.`email` AS t1_r1, `users`.`password` AS t1_r2, `users`.`create_date` AS t1_r3, `users`.`last_updated` AS t1_r4, `users`.`last_login` AS t1_r5, `users`.`user_type` AS t1_r6, `users`.`status` AS t1_r7, `users`.`fb_user_id` AS t1_r8, `couple_detail`.`id` AS t2_r0, `couple_detail`.`user_id` AS t2_r1, `couple_detail`.`fname` AS t2_r2, `couple_detail`.`lname` AS t2_r3, `couple_detail`.`fiance_fname` AS t2_r4, `couple_detail`.`fiance_lname` AS t2_r5, `couple_detail`.`phone` AS t2_r6, `couple_detail`.`address1` AS t2_r7, `couple_detail`.`address2` AS t2_r8, `couple_detail`.`city` AS t2_r9, `couple_detail`.`state` AS t2_r10, `couple_detail`.`country` AS t2_r11, `couple_detail`.`zipcode` AS t2_r12, `couple_detail`.`couple_role` AS t2_r13, `couple_detail`.`fiance_role` AS t2_r14, `couple_detail`.`logo` AS t2_r15, `couple_detail`.`status` AS t2_r16, `couple_detail`.`completed_registration` AS t2_r17, `couple_detail`.`weddingful_cents` AS t2_r18, `vendors_deal_purchases`.`user_id` AS t3_r0, `vendors_deal_purchases`.`email` AS t3_r1, `vendors_deal_purchases`.`password` AS t3_r2, `vendors_deal_purchases`.`create_date` AS t3_r3, `vendors_deal_purchases`.`last_updated` AS t3_r4, `vendors_deal_purchases`.`last_login` AS t3_r5, `vendors_deal_purchases`.`user_type` AS t3_r6, `vendors_deal_purchases`.`status` AS t3_r7, `vendors_deal_purchases`.`fb_user_id` AS t3_r8, `vendor_detail`.`id` AS t4_r0, `vendor_detail`.`user_id` AS t4_r1, `vendor_detail`.`business_name` AS t4_r2, `vendor_detail`.`business_phone` AS t4_r3, `vendor_detail`.`first_name` AS t4_r4, `vendor_detail`.`last_name` AS t4_r5, `vendor_detail`.`url` AS t4_r6, `vendor_detail`.`address1` AS t4_r7, `vendor_detail`.`address2` AS t4_r8, `vendor_detail`.`city` AS t4_r9, `vendor_detail`.`state` AS t4_r10, `vendor_detail`.`country` AS t4_r11, `vendor_detail`.`zipcode` AS t4_r12, `vendor_detail`.`business_description` AS t4_r13, `vendor_detail`.`tagline` AS t4_r14, `vendor_detail`.`logo` AS t4_r15, `vendor_detail`.`logo_caption` AS t4_r16, `vendor_detail`.`store_type` AS t4_r17, `vendor_detail`.`vendor_type` AS t4_r18, `vendor_detail`.`signup_pitch_seen` AS t4_r19, `vendor_detail`.`signup_complete` AS t4_r20, `vendor_detail`.`profile_views` AS t4_r21, `vendor_detail`.`hash_key` AS t4_r22, `vendor_detail`.`available_credits` AS t4_r23, `vendor_detail`.`credit_expire_on` AS t4_r24, `vendor_detail`.`promotion_title` AS t4_r25, `vendor_detail`.`promotion_text` AS t4_r26, `vendor_detail`.`promotion_posted_on` AS t4_r27, `vendor_detail`.`notes` AS t4_r28, `vendor_detail`.`last_updated` AS t4_r29, `vendor_detail`.`claim_date` AS t4_r30, `vendor_detail`.`profile_percentage` AS t4_r31, `vendor_detail`.`vendor_url` AS t4_r32, `vendor_detail`.`status` AS t4_r33, `vendor_detail`.`twilio_number` AS t4_r34, `coupons`.`id` AS t5_r0, `coupons`.`coupon_code` AS t5_r1, `coupons`.`region_id` AS t5_r2, `coupons`.`category_id` AS t5_r3, `coupons`.`expiry` AS t5_r4, `coupons`.`max_uses` AS t5_r5, `coupons`.`deal_id` AS t5_r6, `coupons`.`discount_cents` AS t5_r7, `coupons`.`discount_percent` AS t5_r8, `coupons`.`weddingful_cents_awarded` AS t5_r9, `coupons`.`weddingful_cents_percent` AS t5_r10, `coupons`.`used_count` AS t5_r11, `coupons`.`affiliate_id` AS t5_r12, `coupons`.`created_at` AS t5_r13, `coupons`.`updated_at` AS t5_r14 FROM `deal_purchases` INNER JOIN `users` ON `users`.`user_id` = `deal_purchases`.`couple_id` INNER JOIN `couple_detail` ON `couple_detail`.`user_id` = `users`.`user_id` INNER JOIN `users` `vendors_deal_purchases` ON `vendors_deal_purchases`.`user_id` = `deal_purchases`.`vendor_id` INNER JOIN `vendor_detail` ON `vendor_detail`.`user_id` = `vendors_deal_purchases`.`user_id` LEFT OUTER JOIN `coupons` ON `coupons`.`id` = `deal_purchases`.`coupon_id` LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id WHERE (CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE '%keifatosweet@hotmail.com%' OR vendor_detail.business_name LIKE '%keifatosweet@hotmail.com%' OR users.email LIKE '%keifatosweet@hotmail.com%' OR coupons.coupon_code LIKE '%keifatosweet@hotmail.com%' OR deal_purchases.voucher_code LIKE '%keifatosweet@hotmail.com%') ORDER BY created_at
如果人们有改进的建议,我愿意重构查询的构建方式,但我真正想要的是如果搜索参数包含a,则不会爆炸的方法。对此方面的任何建议都将不胜感激。
答案 0 :(得分:1)
@ JofoCodin的观点让我尝试重写我左边连接的方式,以映射到rails生成的版本。
DealPurchase.order('created_at DESC').includes(
:couple => :couple_detail, :vendor => :vendor_detail
).joins(:couple => :couple_detail).joins(:vendor => :vendor_detail).joins(
"LEFT OUTER JOIN `coupons` ON `coupons`.`id` = `deal_purchases`.`coupon_id`"
).where(
"CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE ? OR " +
"vendor_detail.business_name LIKE ? OR " +
"users.email LIKE ? OR " +
"coupons.coupon_code LIKE ? OR " +
"deal_purchases.voucher_code LIKE ?",
"%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%"
).includes(:coupon)
这很有效,Rails停止在优惠券上创建额外的连接条款。我希望我能理解发生了什么,但这至少解决了具体问题。
感谢JofoCodin的帮助。