我有一个聊天应用程序数据库。
CREATE TABLE Users (uid int PRIMARY KEY, name text, phone text );
CREATE TABLE Messages (recipient int REFERENCES Users(uid), sender int
REFERENCES Users(uid), time timestamp NOT NULL, message text NOT NULL,
PRIMARY KEY (recipient, sender, time));
http://www.sqlfiddle.com/#!9/bd36d1
我想为发送最多消息的5个用户中的每个用户定义该用户发送的消息的平均长度。
我写了以下查询:
SELECT avg(strlen(message))
FROM Messages
WHERE sender IN
(SELECT *
FROM (SELECT sender, COUNT(sender) AS NumberOfMessages
FROM Messages
GROUP BY sender) AS MessagesPerSender
ORDER BY NumberOfMessages DESC
LIMIT 5)
首先,此查询正确吗?它给我想要的结果吗?问题是我根本无法运行它,原因是我得到了错误:
“此版本的MySQL尚不支持'LIMIT&IN / ALL / ANY / SOME子查询”
答案 0 :(得分:2)
对于mysql而言,这可能不是正确的方法
select sender,avg(length(message)),count(*)
from messages
group by sender
order by avg(length(message)) desc limit 5;
+--------+----------------------+----------+
| sender | avg(length(message)) | count(*) |
+--------+----------------------+----------+
| 1 | 9.0000 | 1 |
| 9 | 5.5000 | 2 |
| 2 | 5.0000 | 1 |
+--------+----------------------+----------+
3 rows in set (0.00 sec)
请注意,这可能无法以您想要的方式处理抽奖。
答案 1 :(得分:2)
您的代码中有2个错误:
首先,您不能在MYSQL中使用strlen
。那是微软
SQL Server方言而是需要使用length
。
第二,在您使用的子查询中,您正在使用两列 而不是一个。这将导致查询失败,因为等于 运算符仅需等于一列中的值。
这是您的查询:
select u.name, avg(length(m.message)), count(*)
from Messages m
inner join Users u on m.sender = u.uid
group by u.name
order by avg(length(m.message)) desc limit 5;
由于我为您提供了发件人的姓名而不是其ID,所以我改进了P. Salmon的回答。
希望这会有所帮助:)
答案 2 :(得分:1)
要找出答案,我将DMBS从MySQL更改为支持内部限制的Postgres。您的查询语法正确,但strlen()
函数除外,正确的语法是length()
。
但是,您的查询失败的原因很简单:您正在执行where sender in (subquery)
,尽管子查询返回两个字段。 in
运算符仅适用于单个字段查询。而且,您的子查询由两个查询组成,可以简化为一个查询。以下查询适用于Postgres 9.6,并且应适用于具有内部限制支持的任何版本的MySQL:
SELECT avg(length(message))
FROM Messages
WHERE sender IN (
SELECT sender
FROM Messages
GROUP BY sender
ORDER BY COUNT(sender) DESC
LIMIT 5
)
在您的样本数据上运行时,它会产生以下结果:
+----------+
| avg |
+----------+
| 6.25 |
+----------+
有效的SQL提琴(Postgres 9.6):http://www.sqlfiddle.com/#!17/bd36d/6/0