2012-04-26 285 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