Reputation: 314
I have a table with: id, client, domain and bytes. I have a query that gets the top 3 users either by client:
SELECT client FROM log
GROUP BY 1
ORDER BY SUM(bytes) DESC
LIMIT 3
or by domain
SELECT domain FROM log
GROUP BY 1
ORDER BY SUM(bytes) DESC
LIMIT 3
Is there a way in MySQL to get this two mixed without a stored procedure? For example, get the top 3 clients, each client row followed by the top 3 domains used BY THAT CLIENT in a single query execution?
For example, to get the top 3 domain usage from client 192.168.1.1:
SELECT domain FROM log
WHERE client = '192.168.1.1'
GROUP BY 1
ORDER BY SUM(bytes) DESC
LIMIT 3
So for each row in query #1, somehow this query should be executed. So far I got to show a concatenated list of top domains for each client, sadly not related to the same client because I can't access outer_client
in subquery:
SELECT client AS outer_client, top_domain
FROM log
JOIN (
SELECT GROUP_CONCAT(t.domain) AS top_domain
FROM (
SELECT domain
FROM log
WHERE client = outer_client
GROUP BY 1
ORDER BY SUM(bytes)
LIMIT 5
) t
) k
GROUP BY client
ORDER BY SUM(bytes)
LIMIT 5;
Upvotes: 1
Views: 251
Reputation: 314
Here it is:
select client,
substring_index(group_concat(domain order by sumbytes desc), ',', 5) as top5domains
from (
select client, domain, sum(bytes) as sumbytes
from log
group by client, domain
) cd
group by client
order by sum(sumbytes) desc
limit 5;
Courtesy of @Gordon Linoff here: MySQL GROUP_CONCAT from subquery
Upvotes: 0
Reputation: 3533
One solution:
http://sqlfiddle.com/#!2/cc1b1/2/0
SELECT client
, (SELECT domain
FROM log
WHERE client=top_clients.client
GROUP BY client, domain
ORDER BY SUM(bytes) DESC
LIMIT 1) domain1
, (SELECT domain
FROM log
WHERE client=top_clients.client
GROUP BY client, domain
ORDER BY SUM(bytes) DESC
LIMIT 1 OFFSET 1) domain2
, (SELECT domain
FROM log
WHERE client=top_clients.client
GROUP BY client, domain
ORDER BY SUM(bytes) DESC
LIMIT 1 OFFSET 2) domain3
FROM (SELECT client FROM log GROUP BY client ORDER BY SUM(bytes) DESC LIMIT 3) top_clients;
My output:
+-------------+--------------+--------------+-------------+
| client | domain1 | domain2 | domain3 |
+-------------+--------------+--------------+-------------+
| 192.168.1.1 | google.com | facebook.com | twitter.com |
| 192.168.1.2 | facebook.com | twitter.com | NULL |
+-------------+--------------+--------------+-------------+
Upvotes: 2
Reputation: 1469
According to your question, you are ordering by the same thing in each example. If that's the case, the row you return should have both client and domain already in it. So would this solve your problem?
SELECT client, domain FROM log
GROUP BY 1
ORDER BY SUM(bytes) DESC
LIMIT 3
Upvotes: -1
Reputation: 4669
Assuming you have access to PHPMySQL, and your server allows it, what you're looking for is a VIEW.
You write your SQL to get your data set. And rather than saving it in a temporary table (which would make it static), you save it in a VIEW. Once you have that view, you can always use it the same as if it were a table. In fact, it actually SHOWS the data set in a table format as if that's exactly what it was.
You can run queries against it, with JOINS... Anything you would do with a table.
And it's actual live data.
Upvotes: 0