我有一个庞大的产品数据库。它与另一个价格表有一对多的关系。通过一个查询,我可以很容易地得到特定类别的MIN,MAX和AVG。
SELECT
MIN(gbp.price) AS min,
ROUND(AVG(gbp.price),2) AS ave,
MAX(gbp.price) AS max
FROM sku AS s
INNER JOIN price gbp ON gbp.sid = s.id
但是,我也希望能够获得与之相关的产品的标题 - 尽管进行了多次搜索和重写,我仍然无法解决这个问题。
我的数据类似于......
prod_id | title
===============
1 | prod1
2 | prod2
3 | prod3
4 | prod4
5 | prod5
6 | prod6
7 | prod7
price_id | prod_id | price | price_date
=======================================
1 | 1 | 2.99 | 2015/02/01
2 | 1 | 3.99 | 2015/02/12
3 | 2 | 12.99 | 2015/02/01
4 | 3 | 15.99 | 2015/02/01
5 | 4 | 29.99 | 2015/02/01
6 | 5 | 29.99 | 2015/02/01
7 | 5 | 24.99 | 2015/02/12
8 | 6 | 2.99 | 2015/02/01
9 | 7 | 99.99 | 2015/02/01
10 | 7 | 89.99 | 2015/02/12
我会假设其他人可能想要一个与此类似的查询,所以我要求两个答案。
第一个"简单地"要归还......
min | min_title | ave | max | max_title
============================================
2.99 | prod1 | 31.39 | 99.99 | prod7
但是,我想要的真正答案(尽管事实上我甚至无法解决上述问题)都会变得更加棘手。
我想要的实际结果如下表所示......
min | min_title | ave | max | max_title
============================================
2.99 | prod6 | 25.85 | 89.99 | prod7
min
2.99
prod6
2.99
因prod1
max
价已过期。
89.99
prod7
99.99
prod7
因ave
25.85
价已过期。
prod5
因为上述而24.99
,因为{{1}}的价格为{{1}}。
我不期待一切的答案,只是回答第一个问题(粗体)可能会引导我找到第二部分的答案(因为我有类似的查询得到最新的价格等)。
答案 0 :(得分:0)
要解决您的第一个输出,只需使用join来获取这些值:
SELECT min, mint.title, ave, max, maxt.title
FROM (
SELECT
MIN(gbp.price) AS min,
ROUND(AVG(gbp.price),2) AS ave,
MAX(gbp.price) AS max
FROM (SELECT price
FROM price AS gbp
INNER JOIN sku s2 ON gbp.sid = s2.id
ORDER BY prdate DESC
LIMIT 0, 1) AS s
INNER JOIN price gbp ON gbp.sid = s.id
) inq
JOIN price minp ON inq.min = minp.price
JOIN price maxp on inq.max = maxp.price
JOIN prod mint ON minp.prod_id = mint.prod_id
JOIN prod maxt ON maxp.prod_id = maxt.prod_id
我不理解第二次输出的规则。
答案 1 :(得分:0)
这实际上是两个不同的查询(如果计算平均值,则为三个查询)。交叉连接只是将最小值和最大值的两个结果水平拼接在一起。它们显然可以分开并单独执行。
with current_prices as (
select price_id, prod_id, price
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
),
min_current_prices as (
select price, min(prod_id) as prod_d /* arbitrary selected representative */
from current_prices
where price = (
select min(price)
from current_prices
)
group by price
),
max_current_prices as (
select price, min(prod_id) as prod_id /* arbitrary selected representative */
from current_prices
where price = (
select max(price)
from current_prices
)
group by price
)
select
m1.price, prod1.title,
(select avg(price) from current_prices) as ave,
m2.price, prod2.title
from
min_current_prices as m1 inner join products as prod1 on prod1.prod_id = m1.prod_id
max_current_prices as m2 inner join products as prod2 on prod2.prod_id = m2.prod_id
我觉得这看起来太复杂了,但你却要求一些非常不寻常的东西。显然可能会有相同的最低/最高价格的产品,因此当两端都有多个产品时会出现问题。
如果您的平台不支持WITH
,则只需替换完整查询:
select
min_current_price.price as min_price, min_prod.title as min_title,
(
select avg(price)
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
) as ave,
max_current_price.price as max_price, max_prod.title as max_title
from
(
select price, min(prod_id) as prod_id /* arbitrarily selected representative */
from (
select *
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
) as current_prices
where price = (
select min(price)
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
)
group by price
) as min_current_price
cross join
(
select price, min(prod_id) as prod_id /* arbitrarily selected representative */
from (
select *
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
) as current_prices
where price = (
select max(price)
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
)
group by price
) as max_current_price
inner join products as min_prod on min_prod.prod_id = min_current_price.prod_id
inner join products as max_prod on max_prod.prod_id = max_current_price.
这是使用限制和排序方法在mysql中进行的黑客攻击:
select
minprice.price as min_price, minprod.title as min_title,
(
select avg(price)
from prices
where price_date = (
select max(price_date)
from prices as prices2
where prices2.prod_id = prices.prod_id
)
) as ave,
maxprice.price as max_price, maxprod.title as max_title
from
(
select price_id, price, prod_id
from prices
where not exists ( /* another way of excluding expired prices */
select 1 from prices as p2
where p2.prod_id = prices.prod_id and p2.price_date > prices.prod_id
)
order by price asc
limit 0, 1
) as minprice,
(
select price_id, price, prod_id
from prices
where not exists (
select 1 from prices as p2
where p2.prod_id = prices.prod_id and p2.price_date > prices.prod_id
)
order by price desc
limit 0, 1
) as maxprice
inner join prod as minprod on minprod.prod_id = minprice.prod_id
inner join prod as maxprod on min.prod_id = maxprice.prod_id
答案 2 :(得分:0)
SELECT t1.min, s.title AS min_title, t1.ave, t1.max, s2.title AS max_title
FROM (SELECT
MIN(gbp.price) AS min,
ROUND(AVG(gbp.price),2) AS ave,
MAX(gbp.price) AS max
FROM sku AS s
INNER JOIN price gbp ON (gbp.sid = s.id)
) t1
INNER JOIN (SELECT gbp.price, MAX(gbp.prod_id) AS MaxProdID
FROM price gbp
WHERE NOT EXISTS(
SELECT p2.price_id
FROM price p2
WHERE p2.price_id > gbp.price_id
AND p2.prod_id = gpb.prod_id
)
GROUP BY gbp.price
) minprice ON (minprice.price = t1.min)
INNER JOIN sku s ON (s.id = minprice.MaxProdID)
INNER JOIN (SELECT gbp.price, MAX(gbp.prod_id) AS MaxProdID
FROM price gbp
WHERE NOT EXISTS(
SELECT p2.price_id
FROM price p2
WHERE p2.price_id > gbp.price_id
AND p2.prod_id = gpb.prod_id
)
GROUP BY gbp.price
) maxprice ON (maxprice.price = t1.max)
INNER JOIN sku s2 ON (s2.id = maxprice.MaxProdID)