来自 MySQL 数据的记分牌
Posted
技术标签:
【中文标题】来自 MySQL 数据的记分牌【英文标题】:Scoreboard from MySQL data 【发布时间】:2020-08-13 22:12:38 【问题描述】:我有一个包含两个表的数据库。一个保存商品数据,一个保存另一张表中商品的价格统计信息。
物品表 itemid (int, 自增) |名称 (varchar) |描述 (varchar) | added_on(日期时间)
统计表: id (int, 自增) |项目 (int) |价格(整数) | date_seen (日期时间)
第一个表中的“itemid”列是唯一的,在第二个表中被引用为“item”每次检查一个项目的价格时,如果价格与上次相比发生变化,它就会被添加到统计表中已被检查
例如,表格如下所示:
Item Table
itemid (int, auto increment) | name (varchar) | description (varchar) | added_on (datetime)
1 | testproduct1 | This is a testproduct | 2020-04-23 16:43:47
2 | testproduct2 | This is a testproduct too | 2020-04-23 17:08:32
stats table:
id (int, auto increment) | item (int) | price (int) | date_seen ( datetime )
1 | 1 | 7 | 2020-04-23 09:12:00
2 | 1 | 4 | 2020-04-23 09:34:00
3 | 2 | 8 | 2020-04-23 09:12:00
4 | 2 | 6 | 2020-04-23 09:34:00
5 | 1 | 3 | 2020-04-23 10:08:00
6 | 2 | 4 | 2020-04-23 10:08:00
假设我想获得今天添加的 Top5 项目,按 last_seen DESC 排序,然后按价格 DESC 排序,因此您将获得以下输出:
NAME |PRICE| date_seen
testproduct2 | 4 | 2020-04-23 10:08:00
testproduct1 | 3 | 2020-04-23 10:08:00
我会怎么做呢?我尝试了以下
SELECT *
FROM (
SELECT
i.itemid,
i.name,
s.price,
s.date_seen AS sdate,
FROM
items i
INNER JOIN stats s
ON i.itemid = s.item
WHERE i.added_on LIKE '2020-04-23%'
) AS sub
ORDER BY `sub`.`sdate` DESC,`sub`.`price` DESC
GROUP BY i.itemid
但是,这里似乎不允许 group by,没有它,查询可以工作,我得到的结果是按日期排序的,但价格根本没有排序。获得所需结果的正确查询是什么?提前致谢!
【问题讨论】:
请学习如何正确使用GROUP BY
。 GROUP BY
没有聚合有什么意义? SELECT * ... GROUP BY
不应该运行,因为它没有意义。
【参考方案1】:
你在最后的内部选择中有一个逗号',那太多了
并且 GROUP By 必须在 THE ORDER BY
之前SELECT *
FROM (
SELECT
i.itemid,
i.name,
s.price,
s.date_seen AS sdate
FROM
items i
INNER JOIN stats s
ON i.itemid = s.item
WHERE i.added_on LIKE '2020-04-23%'
) AS sub
GROUP BY itemid
ORDER BY `sub`.`sdate` DESC,`sub`.`price` DESC
要获取最后日期和价格,您必须使用子查询获取正确的统计数据行。
SELECT
i.itemid,
i.name,
s.price,
s.date_seen AS sdate
FROM
items i
INNER JOIN stats s
ON i.itemid = s.item
WHERE s.date_seen = (SELECT MAX(date_seen)
FROM stats WHERE date_seen <= i.added_on and s.item = i.itemid)
做事的方法不止一种。
SELECT
i.itemid,
i.name,
s.price,
s.date_seen AS sdate
FROM
items i
INNER JOIN stats s
ON i.itemid = s.item
INNER JOIN
(SELECT MAX(date_seen) maxdate,item FROM stats GROUP BY item) s1 ON s1.item = s.item AND s.date_seen = s1.maxdate;
查看新示例https://www.db-fiddle.com/f/wUqVKNZy96RjR7hTk3md7o/3
【讨论】:
感谢您的快速回复。我刚刚进行了必要的更改,但它现在似乎抓住了它找到的第一个价格,即 2020-04-23 09:12:00 的价格,而不是 2020-04-23 10:08:00 的价格。这就是为什么我认为我会订购(所以我有最新的日期/时间,然后分组,希望只获得每个项目的最新可用数据。我需要对此查询进行哪些更改,使其返回每件商品的最新价格数据? 不知何故,这个查询也触发了 504 被拒绝(就像 GMB 提供的查询一样。)我将对此进行一些故障排除。但再次感谢您的帮助! 请检查链接的小提琴,看看您是否可以重现并写下 complete 错误消息 小提琴奏效了,尽管它没有将高价排序为低价。但是当使用查询时它永远不会返回。那就是 phpMyAdmin 中 504 的来源。直接在 mysql CLI 上运行查询,永远不会返回,它只是挂起。数据集并没有那么大,两个表都包含 80.000 到 100.000 条记录。 正如我所说的完整的错误信息,这很重要。我检查过,但它也适用于较旧的 mysql 版本。【参考方案2】:您可以使用子查询过滤每个项目的最新 stats
记录:
select i.name, s.price, s.date_seen
from item i
inner join stats s on s.item = i.itemid
where s.date_seen = (
select max(s1.date_seen)
from stats s1
where
s1.date_seen >= '2020-04-23'
and s1.date_seen < '2020-04-24'
and s1.item = s.item
)
order by s.date_seen desc, s.price
请注意,我更改了日期的谓词:没有函数起作用,因此它可能会利用索引。
【讨论】:
感谢您的询问。当测试 mysql 在一段时间后返回 504 被拒绝时,我现在将对其进行故障排除。再次感谢。以上是关于来自 MySQL 数据的记分牌的主要内容,如果未能解决你的问题,请参考以下文章