简体   繁体   English

MYSQL控制流功能

[英]MYSQL- Control Flow Functions

Been working on this for a couple of hours now and I wonder if there is a recommended solution for this in SQL or if I am better off putting this in my application logic instead of the database. 现在已经进行了两个小时的工作,我想知道是否有建议的SQL解决方案,或者最好将其放在应用程序逻辑中而不是数据库中。 I'd prefer the former. 我希望前者。

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$$

I need come up with the best estimate for average rate of each product and vendor combination, given a city, state & country. 考虑到城市,州和国家/地区,我需要针对每种产品和供应商组合的平均费率得出最佳估计。 Each vendor can have a different number of products. 每个供应商可以拥有不同数量的产品。 Also, the number of vendors in each city can be different. 此外,每个城市的供应商数量可能不同。 The logic needs to be 逻辑需要

  1. Return data for records matching city, state and country, if a match is found. 如果找到匹配项,则返回匹配城市,州和国家/地区的记录的数据。
  2. If a match is not found, try to find results based on state & country. 如果找不到匹配项,请尝试根据州和国家/地区查找结果。
  3. If that doesn't return anything either, find results based on country only 如果也没有返回任何结果,则仅根据国家/地区查找结果
  4. Last resort, use all records to come up with the average rate of each product, vendor combination 不得已时,使用所有记录得出每种产品,供应商组合的平均比率
  5. There is additional logic for other columns, but they all follow the same pattern as location. 其他列还有其他逻辑,但是它们都遵循与位置相同的模式。

The first query will be something like 第一个查询将类似于

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 

I have been playing around with COALESCE, CASE, IFNULL, but can't get the queries to work. 我一直在玩COALESCE,CASE,IFNULL,但是无法使查询正常工作。 I can do it in the application layer, but I'd have to make multiple calls to the database as there is high likelihood that the first case will not be met. 我可以在应用程序层中完成此操作,但是由于极有可能无法满足第一种情况,因此我必须对数据库进行多次调用。

The ideal solution would be something like 理想的解决方案是

COALESCE(select_city_state_cntr, select_state_cntry, select_cntry);

Let me know if something is missing and I'll add more details as required. 让我知道是否缺少某些东西,我将根据需要添加更多详细信息。

Thank you 谢谢

Here's a possible solution. 这是一个可能的解决方案。 Query all three ways, and use LIMIT to take the first one that matches. 查询所有三种方式,并使用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;

One way would be: 一种方法是:

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;

and a select query: 和选择查询:

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;

This should give you right results (if I got you requirements right), though its not efficient, since it calculates all options even in case exect city is found: 这应该给您正确的结果(如果我满足您的要求),尽管效率不高,因为即使在找到exect城市的情况下,它也会计算所有选项:

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;

For state average, you cannot use AVG, since query matches all rows (in country), thus the query should be like that: 对于平均状态,您不能使用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;

Now for firth "last resort" option, drop country requirement, and replace AVG(rate) AS wholeCountryData part with SUM((country = 'United States') * rate) / SUM(country = 'United States') AS wholeCountryData 现在,对于第一个“最后一招”选项,删除国家/地区要求,并用SUM((country = 'United States') * rate) / SUM(country = 'United States') AS wholeCountryData替换AVG(rate) AS wholeCountryData部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM