【问题标题】:MYSQL - output extra column based on a certain conditionMYSQL - 根据特定条件输出额外的列
【发布时间】:2017-04-20 22:04:03
【问题描述】:

首先,我想为提供这么弱的标题道歉;我无法用更好的方式来描述它。

考虑以下情况:我们有三张表,一张用于users,一张用于records,一张用于ratings。这些表是不言自明的,但数据库的架构如下:

+---------------------+
| Tables_in_relations |
+---------------------+
| records             |
| ratings             |
| users               |
+---------------------+

records 表的架构如下:

+----------+----------------------+------+-----+---------+----------------+
| Field    | Type                 | Null | Key | Default | Extra          |
+----------+----------------------+------+-----+---------+----------------+
| id       | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |
| title    | varchar(256)         | NO   |     | NULL    |                |
| year     | int(4)               | NO   |     | NULL    |                |
+----------+----------------------+------+-----+---------+----------------+

users 表的架构如下:

+----------+----------------------+------+-----+---------+----------------+
| Field    | Type                 | Null | Key | Default | Extra          |
+----------+----------------------+------+-----+---------+----------------+
| id       | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |
| email    | varchar(256)         | NO   |     | NULL    |                |
| name     | varchar(256)         | NO   |     | NULL    |                |
| password | varchar(256)         | NO   |     | NULL    |                |
+----------+----------------------+------+-----+---------+----------------+

ratings 表显然是在其中存储评级与 record_id 和 user_id 并用作关系表。

它的架构如下:

+----------+----------------------+------+-----+---------+----------------+
| Field    | Type                 | Null | Key | Default | Extra          |
+----------+----------------------+------+-----+---------+----------------+
| id       | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |
| record_id| smallint(5) unsigned | NO   | MUL | NULL    |                |
| user_id  | smallint(5) unsigned | NO   | MUL | NULL    |                |
| rating   | int(1)               | NO   |     | NULL    |                |
+----------+----------------------+------+-----+---------+----------------+

现在,在我的应用程序中,我有一个搜索功能,可以根据某个关键字获取记录。输出还应包括某条记录的平均评分和每条记录的评分总数。这可以通过以下查询来完成:

SELECT re.id, re.title, re.year, ROUND(avg(ra.rating)) as avg_rate,
COUNT(ra.record_id) as total_times_rated
FROM records re
LEFT JOIN ratings ra ON ra.record_id = re.id
GROUP BY re.id;

这会给我以下输出:

+----+------------------------+------+----------+-------------------+
| id | title                  | year | avg_rate | total_times_rated |
+----+------------------------+------+----------+-------------------+
|  1 | Test Record 1          | 2008 |        3 |                 4 |
|  2 | Test Record 2          | 2012 |        2 |                 4 |
|  3 | Test Record 3          | 2003 |        3 |                 4 |
|  4 | Test Record 4          | 2012 |        3 |                 3 |
|  5 | Test Record 5          | 2003 |        2 |                 3 |
|  6 | Test Record 6          | 2006 |        2 |                 3 |
+----+------------------------+------+----------+-------------------+

问题:

现在,棘手的部分来了,至少对我来说是这样。在我的应用程序中,您可以搜索是否登录的记录,如果登录,我还想在上述查询中包含用户自己的评分值。

我知道我可以通过读取会话值来运行条件来检查用户是否已登录,并据此执行相应的查询。我只是不知道如何将某个用户的个人评分值包含到上述查询中。

【问题讨论】:

  • 如何计算用户评分?是匹配记录的所有评分中的SUM
  • 这是一个个体值。用户每次对记录进行评分,都会存储在ratings表中(record_id、user_id和实际评分)
  • 这样做的目的是如果他/她已经根据关键字对记录进行了评分,则用户可以查看他/她自己的评分值。

标签: mysql database relationship


【解决方案1】:

您可以通过在列中添加SELECT 查询来在结果中添加用户评分:

SELECT re.id, re.title, re.year, ROUND(avg(ra.rating)) as avg_rate,
COUNT(ra.record_id) as total_times_rated,
(SELECT rating FROM ratings WHERE user_id = ? AND record_id = re.id) as user_rating
FROM records re
LEFT JOIN ratings ra ON ra.record_id = re.id
GROUP BY re.id;

我们可以从会话中获取user_id 并将其传递给此查询,以便在结果中生成user_rating 列。

假设用户可以多次评价一条记录,我使用了SUM。如果没有,我们可以将其从查询中删除。

更新

如果您不希望 GROUP BY 考虑该值,则可以将现有查询包装到另一个查询中并向其中添加一列,例如:

SELECT a.id, a.title, a.year, a.avg_rate, a.total_times_rated,
(SELECT rating FROM ratings WHERE user_id = ? AND record_id = a.id) as user_rating
FROM (SELECT re.id as id, re.title as title, re.year as year, ROUND(avg(ra.rating)) as avg_rate,
COUNT(ra.record_id) as total_times_rated
FROM records re
LEFT JOIN ratings ra ON ra.record_id = re.id
GROUP BY re.id) a;

【讨论】:

  • 刚试了一下,返回如下错误:ERROR 1242 (21000): Subquery returns more than 1 row。我认为这是因为可能有多个记录用户已评级并因此给出错误。是的,用户不能多次评价一条记录,这就是为什么我从你的答案中删除了SUM
  • 在查询中又添加了一个条件,现在试试?
  • 好吧,现在我得到user_rating 值,如果用户对记录进行评分,NULL 如果没有。但是,现在它从一条记录中获取total_times_recordedavg_rate,并将其输出到以前没有发生的所有记录上。奇怪...
  • 嗯,好的,我在答案中添加了另一个查询,你可以再试一次吗?
  • 好的,谢谢!它就像我想要的那样工作。干杯,伙计 :) 这些子查询有时会很棘手。
猜你喜欢
  • 1970-01-01
  • 2021-04-04
  • 2015-08-24
  • 1970-01-01
  • 2015-10-09
  • 2019-08-18
  • 2019-09-20
  • 1970-01-01
  • 2021-05-03
相关资源
最近更新 更多