来自 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 BYGROUP 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 数据的记分牌的主要内容,如果未能解决你的问题,请参考以下文章

在 Angular 中绑定 JSON 数据

如何使用改造从 JSON 中获取数据?

在 C# 中为本地记分板保存数组

MySQL按键获取最高值,然后为其添加排名

使用 GridSearchCV 制作自定义记分器

从列表列表中引用列表