2012-04-26 110 views
3

我想寫一個複雜的SQL查詢,但無法設法使用正確的值獲取結果集。複雜的MySQL查詢

  • coupons表擁有一些在線優惠券。
  • merchants表保存商戶信息,並綁couponscoupons.merchant_id
  • branches表保存商家的分支與latlng值(以計算距離和最近的分支等)和綁merchantsbranches.merchant_id
  • coupons_branches表關係couponsbranches表。
  • places表包含一些特殊的地方,比如商場等,並綁branchesbranches.place_id

下面是我的表結構;

CREATE TABLE IF NOT EXISTS `branches` (
    `branch_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `merchant_id` int(11) unsigned NOT NULL DEFAULT '0', 
    `place_id` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `branch` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `address` varchar(255) COLLATE utf8_unicode_ci DEFAULT '', 
    `postcode` varchar(6) COLLATE utf8_unicode_ci DEFAULT '', 
    `phone` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `fax` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `lat` float(10,6) DEFAULT NULL, 
    `lng` float(10,6) DEFAULT NULL, 
    `status` tinyint(4) unsigned NOT NULL DEFAULT '1', 
    PRIMARY KEY (`branch_id`), 
    KEY `lat` (`lat`), 
    KEY `lng` (`lng`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 

CREATE TABLE IF NOT EXISTS `coupons` (
    `coupon_id` mediumint(9) unsigned NOT NULL AUTO_INCREMENT, 
    `category_id` tinyint(4) unsigned NOT NULL DEFAULT '0', 
    `merchant_id` mediumint(9) unsigned NOT NULL DEFAULT '0', 
    `coupon` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `description` longtext COLLATE utf8_unicode_ci, 
    `start_date` date DEFAULT NULL, 
    `end_date` date DEFAULT NULL, 
    `coupon_usage` int(10) unsigned NOT NULL DEFAULT '0', 
    `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `status` enum('active','passive','deleted','preview') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'active', 
    PRIMARY KEY (`coupon_id`), 
    KEY `start_date` (`start_date`), 
    KEY `end_date` (`end_date`), 
    KEY `merchant_id` (`merchant_id`), 
    KEY `category_id` (`category_id`), 
    KEY `status` (`status`), 
    KEY `created` (`created`), 
    FULLTEXT KEY `description` (`description`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 

CREATE TABLE IF NOT EXISTS `coupons_branches` (
    `branch_id` int(11) unsigned NOT NULL DEFAULT '0', 
    `coupon_id` int(11) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`branch_id`,`coupon_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE TABLE IF NOT EXISTS `merchants` (
    `merchant_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `merchant` varchar(80) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `website` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `status` enum('active','passive','deleted') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'passive', 
    PRIMARY KEY (`merchant_id`), 
    KEY `status` (`status`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 

CREATE TABLE IF NOT EXISTS `places` (
    `place_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, 
    `city_id` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `place` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL, 
    PRIMARY KEY (`place_id`), 
    KEY `place` (`place`), 
    KEY `city_id` (`city_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 

這裏是我的SQL;

SELECT * FROM (SELECT coupons.coupon_id AS c_id, coupons.category_id, coupons.coupon, merchants.merchant_id, merchants.merchant, (((acos(sin((41.02287686 * pi()/180)) * sin((branches.lat * pi()/180)) + cos((41.02287686 * pi()/180)) * cos((branches.lat * pi()/ 180)) * cos(((29.04632806 - branches.lng) * pi()/180)))) * 180/pi()) * 60 * 1.1515 * 1.609344) as distance, COUNT(coupons.coupon_id) AS total_coupons 
FROM (`coupons`) 
INNER JOIN `coupons_branches` ON `coupons`.`coupon_id` = `coupons_branches`.`coupon_id` 
RIGHT OUTER JOIN `branches` ON `coupons_branches`.`branch_id` = `branches`.`branch_id` 
LEFT OUTER JOIN `merchants` ON `coupons`.`merchant_id` = `merchants`.`merchant_id` 
WHERE `coupons`.`status` = 'active' 
AND `merchants`.`status` = 'active' 
GROUP BY `merchants`.`merchant_id` 
HAVING `distance` <= 25000 
ORDER BY `merchants`.`merchant`) as T2 GROUP BY c_id ORDER BY merchant 

我試圖找出商家的總優惠券。我只想列出該商家的最新優惠券。我不想列出所有優惠券。我想先給商家分組,顯示商家有多少優惠券。然後在另一頁上,我將顯示屬於該商家的優惠券。

一切工作很好,除了total_coupons列。總優惠券列計算不正確。如果我在下面寫出類似的話,它會正確計算。

SELECT * FROM (SELECT coupons.coupon_id, coupons.coupon_id AS c_id, coupons.category_id, coupons.coupon, merchants.merchant_id, merchants.merchant, coupons.coupon_usage, COUNT(coupons.coupon_id) AS total_coupons 
FROM (`coupons`) 
LEFT OUTER JOIN `merchants` ON `coupons`.`merchant_id` = `merchants`.`merchant_id` 
WHERE `coupons`.`status` = 'active' 
AND `merchants`.`status` = 'active' 
GROUP BY `merchants`.`merchant_id` 
ORDER BY `merchants`.`merchant`) as T2 GROUP BY c_id ORDER BY merchant 

也有一些是錯誤的branchesplaces表,但我找不到。

+0

你爲什麼在你的查詢中加入'places'表?我沒有看到查詢中使用該表的任何數據? – 2012-04-26 12:21:01

+0

這個查詢有點複雜。有時候我有'where places.place_id = XXX'條款來縮小搜索結果。但是你是對的,這是我的錯誤,在這裏包括'地方'表。我編輯了上述查詢。 – 2012-04-26 12:30:06

+0

total_coupons以何種方式不正確? – Jim 2012-04-26 12:33:39

回答

5

請嘗試將COUNT()的表達式更改爲COUNT(DISTINCT coupons.coupon_id)。如果沒有DISTINCT關鍵字,即使重複的優惠券也被計入商戶優惠券的總金額中。我猜你只能看到目前分發給分支機構的優惠券總和。

+0

馬丁,非常感謝。這工作很好:) – 2012-04-26 14:38:43

+0

很高興聽到這一點,不客氣! :) – 2012-04-26 17:52:47