【问题标题】:Sorting a list based on the average value of field under associated table根据关联表下字段的平均值对列表进行排序
【发布时间】:2016-08-12 23:46:32
【问题描述】:

有两个表格“items”和“ratings”。项目可以有多个评分。

目前我正在尝试根据评级检索“项目”的排序集合。所以,我需要根据评分的平均值对集合进行排序。

因此,我实现了这个查询。

SELECT items.id, items.description, avg(ratings.value) as average
 FROM `items` 
INNER JOIN `ratings` ON `ratings`.`item_id` = `items`.`id` 
WHERE `items`.`type` IN ('Book') 
GROUP BY ratings.item_id 
ORDER BY average desc;

Output(I have not pasted the whole description, since it is too long to fit):
    +-----+----------------------------+---------+
    | id  | description                | average |
    +-----+----------------------------+---------+
    | 241 | Into the intrigue and vio  |  3.0000 |
    | 242 | Teams can be a driving fo  |  2.0000 |
    | 243 | NULL                       |  5.0000 |
    | 244 | In Temptations of the Wes  |  1.0000 |
    | 245 | NULL                       |  4.0000 |
    +-----+----------------------------+---------+

在这里,项目没有相应地排序。

现在,当我从选择中删除描述时,结果是正确的。

因此,假设问题是由于文本字段的长度而发生的,我将描述字段的长度限制为较低的值。在这里,查询也正常工作。 (尝试了多个值后,它在512处找到了断点)

SELECT items.id, left(items.description, 512), avg(ratings.value) as average
 FROM `items` 
INNER JOIN `ratings` ON `ratings`.`item_id` = `items`.`id` 
WHERE `items`.`type` IN ('Book') 
GROUP BY ratings.item_id 
ORDER BY average desc;

输出(对于较小的修整值):

+-----+----------------------------+---------+
| id  | left(items.description,25) | average |
+-----+----------------------------+---------+
| 243 | Into the intrigue and vio  |  5.0000 |
| 245 | Teams can be a driving fo  |  4.0000 |
| 241 | NULL                       |  3.0000 |
| 242 | In Temptations of the Wes  |  2.0000 |
| 244 | NULL                       |  1.0000 |
+-----+----------------------------+---------+

那么,这是错误还是预期行为,还是我错过了什么?

【问题讨论】:

  • 描述文本字段最初有多长?如果您发布两个查询的不同输出示例,也会有所帮助。
  • @Luke :描述是一个字段类型“文本”,因此其中有很长的段落。另外,我已经更新了输出。

标签: mysql sql sorting


【解决方案1】:

好的,所以我开始研究 SQL 中文本字段的使用,正如您所怀疑的那样,这就是问题所在。文本字段应该避免在 SQL 中使用,因为未来版本的 SQL 将不支持它们。直接来自微软的文档..

重要!在 SQL Server 的未来版本中将删除 ntext、text 和 image 数据类型。避免在新的开发工作中使用这些数据类型,并计划修改当前使用它们的应用程序。请改用 nvarchar(max)、varchar(max) 和 varbinary(max)。

您遇到的问题是,当文本长度超过某个值时,文本字段中的文本会存储在行外。看来这就是您的文本字段发生的情况。由于某种原因,这会炸毁查询处理器或幕后的其他东西,并导致您的查询产生意外结果。

要解决此问题,如果您有权修改描述列的数据类型,则应将其切换为所需长度的 varchar。只要列中的数据少于 8000 个字符,您的问题就应该得到解决。如果没有,您将需要将该列拆分为多个 varchar 列,并将较小的文本片段放入每个列中。

我将发布一个链接,指向下面有关 SQL 文本字段的相关讨论。希望对您有所帮助!

SQL Server Text type vs. varchar data type

【讨论】:

  • 感谢@Luke,应该有一些弃用日志,在这些情况下很容易丢失。幸运的是,我刚刚开始一个新项目,所以不必担心迁移数据。我将更改字段类型,甚至改用 postgreSQL :D
【解决方案2】:

您是否尝试过对这些列进行分组:

SELECT items.id, items.description, avg(ratings.value) as average
FROM `items` 
INNER JOIN `ratings` ON `ratings`.`item_id` = `items`.`id` 
WHERE `items`.`type` IN ('Book') 
GROUP BY items.id, items.description
ORDER BY average desc;

【讨论】:

  • 不,这是返回基于“items.id”降序排序的列表
  • 所以当您的查询显示“ORDER BY average desc”时,您告诉我它不是按平均排序的?
  • 请看select语句,average只是一个命名空间“avg(ratings.value) as average”
  • 是的,该值包含每个 item_id 的平均评分。并对其进行排序,将根据该值对结果进行排序。那是你的问题,不是吗?因此,平均评分最高的项目将首先返回结果。
  • 是的,它应该以这种方式工作,但由于文本字段“描述”,返回的集合没有按正确的顺序返回。在用代码玩了一下之后,我想减少描述的长度,查询工作正常。所以,我问这是一个错误还是需要以其他方式完成。
猜你喜欢
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多