1

现在已经为此工作了几个小时,我想知道在 SQL 中是否有推荐的解决方案,或者我是否最好将它放在我的应用程序逻辑而不是数据库中。我更喜欢前者。

CREATE TABLE `rate_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(100) DEFAULT NULL,
`rate_type` varchar(45) DEFAULT NULL,
`rate` int(11) DEFAULT NULL,
`vendor` varchar(45) DEFAULT NULL,
`product` varchar(45) DEFAULT NULL,
`days_to_pickup` int(11) DEFAULT NULL,
`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`state` varchar(45) DEFAULT NULL,
`country` varchar(45) DEFAULT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=787 DEFAULT CHARSET=latin1$$

在给定城市、州和国家/地区的情况下,我需要对每种产品和供应商组合的平均费率进行最佳估计。每个供应商可以有不同数量的产品。此外,每个城市的供应商数量可能不同。逻辑必须是

  1. 如果找到匹配项,则返回匹配城市、州和国家/地区的记录数据。
  2. 如果未找到匹配项,请尝试根据州和国家/地区查找结果。
  3. 如果这也没有返回任何内容,请仅根据国家/地区查找结果
  4. 不得已,使用所有记录得出每个产品、供应商组合的平均费率
  5. 其他列还有其他逻辑,但它们都遵循与位置相同的模式。

第一个查询将类似于

select avg(rate) rate, vendor, product from rate_info
where city = 'Boston'
and state = 'MA'
and country = 'United States'
and rate_type = 'REGULAR'
and days_to_pickup >= 4
group by vendor, product 

我一直在玩 COALESCE、CASE、IFNULL,但无法让查询正常工作。我可以在应用程序层做到这一点,但我必须多次调用数据库,因为第一种情况很可能不会得到满足。

理想的解决方案是

COALESCE(select_city_state_cntr, select_state_cntry, select_cntry);

让我知道是否缺少某些内容,我会根据需要添加更多详细信息。

谢谢

4

3 回答 3

1

这是一个可能的解决方案。查询所有三种方式,并使用 LIMIT 取第一个匹配的方式。

SELECT * FROM (
 (SELECT SUM(population) AS population, city, state, country
  FROM POPULATION
  WHERE (city, state, country) = (?, ?, ?))
 UNION ALL
 (SELECT SUM(population), NULL, state, country
  FROM POPULATION
  WHERE (state, country) = (?, ?))
 UNION ALL
 (SELECT SUM(population), NULL, NULL, country
  FROM POPULATION
  WHERE (country) = (?))) AS t
WHERE t.population IS NOT NULL
LIMIT 1;
于 2013-02-14T19:40:15.827 回答
0

一种方法是:

CREATE TABLE `population` (
  `city` varchar(64) NOT NULL,
  `state` varchar(64) NOT NULL,
  `country` varchar(64) NOT NULL,
  `population` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

和一个选择查询:

SELECT city, state, country, population
  FROM population
 WHERE country = '<country>' AND state = '<state>' AND city = '<city>'
UNION
SELECT null, state, country, sum(population)
  FROM population
 WHERE country = '<country>' AND state = '<state>'
 GROUP BY state
UNION
SELECT null, null, country, sum(population)
  FROM population
 WHERE country = '<country>'
 LIMIT 1;
于 2013-02-14T19:44:21.287 回答
0

这应该会给你正确的结果(如果我的要求正确的话),虽然它效率不高,因为即使找到了执行城市,它也会计算所有选项:

SELECT 
  (city = 'Boston') * rate AS exactCityData, 
  SUM((city != 'Boston' AND state = 'MA') * rate) AS wholeStateData, 
  SUM((city != 'Boston' AND state != 'MA' AND country = 'United States') * rate) AS wholeCountryData
WHERE country = 'United States'
GROUP BY vendor, product;

对于州平均值,您不能使用 AVG,因为查询匹配所有行(在国家/地区),因此查询应该是这样的:

SELECT 
  (city = 'Boston') * rate AS exactCityData, 
  SUM((state = 'MA') * rate) / SUM(state = 'MA') AS wholeStateData, 
  AVG(rate) AS wholeCountryData
WHERE country = 'United States'
GROUP BY vendor, product;

现在对于第一个“最后的手段”选项,放弃国家要求,并将AVG(rate) AS wholeCountryData部分替换为SUM((country = 'United States') * rate) / SUM(country = 'United States') AS wholeCountryData

于 2013-02-14T21:38:40.897 回答