Reputation: 195
I have a database for a chat application.
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
I want to define, for each of the 5 users which have sent the most messages, the average length of messages that have been sent by this user.
I have written the following query:
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)
To start with, is this query correct? Does it give me the desired result? The problem is I can't run it at all cause I get the error:
"This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery"
Upvotes: 1
Views: 762
Reputation: 6884
You had 2 errors in your code:
first of all you cannot use strlen
in MYSQL. That is an Microsoft
SQL Server dialect Instead you need to use length
.
Secondly, in the subquery you used, you were using two columns instead on one. This will cause the query to fail because the equals operator needs to be equal to the value in only one column.
So here is your query:
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;
I improved on P. Salmon's answer since I provided you with the name of the sender rather than their ID.
Hope this helps :)
Upvotes: 2
Reputation: 17615
Not the right approach for mysql this may do
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)
Note this may not deal with draws in the way you want.
Upvotes: 2
Reputation: 1616
To find out, I have changed the DMBS from MySQL to Postgres, which supports inner limit. Your query has correct syntax, except the strlen()
function, the correct one is length()
.
However, your query fails for a simple reason: you are doing a where sender in (subquery)
, although your subquery returns two fields. The in
operator only works with single field queries. Moreover, your subquery is composed of two queries, which can be simplified to one. The following query works on Postgres 9.6, and should work on whatever version of MySQL with inner limit support:
SELECT avg(length(message))
FROM Messages
WHERE sender IN (
SELECT sender
FROM Messages
GROUP BY sender
ORDER BY COUNT(sender) DESC
LIMIT 5
)
It produces the following result when run on your sample data:
+----------+
| avg |
+----------+
| 6.25 |
+----------+
Working SQL Fiddle (Postgres 9.6): http://www.sqlfiddle.com/#!17/bd36d/6/0
Upvotes: 1