MySQL Select and LIMIT - mysql

I have a table
id ip
1 127.0.0.1
2 127.0.0.1
3 127.0.0.1
4 192.168.2.2
5 192.168.70.1
6 217.11.24.65
I need to get rows from 3 ips i.e. if i have limit 3 I must to get 1,2,3,4,5
If Limit 2 - 1,2,3,4
i.e. limited by unique IPs
SELECT id FROM ips LIMIT 3 // returns 1,2,3 but i want 1,2,3,4,5
Sorry for bad english and thanks for understanding.

SELECT id
FROM ips
WHERE ip IN (SELECT DISTINCT ip FROM ips ORDER BY id LIMIT 3)
As MySQL 5.5 doesn't yet support LIMIT inside of ANY, here's a simple workaround:
SELECT id
FROM ips
WHERE ip IN (SELECT * FROM (SELECT DISTINCT ip FROM ips ORDER BY id LIMIT 3) alias)

Related

Select only 1 row after ordering

Is it possible to get only 1 row after ordering? I don't want to load DB so much, so I want to get only 1 row (it may be from the middle), here is an example:
ID
User
Points
1
user1
10
2
user2
60
3
user3
45
I want to get the fe. the second user after ORDER BY `points` DESC, so the table will look like
ID
User
Points
2
user2
60
3
user3
45
1
user1
10
The second user is user3, and I want to return just that one row. It is possible? Or do I need to get all and just LIMIT it?
If you are using MySql 8+ you can use rank, for example:
with r as (
select * , Rank() over(order by points desc) rnk
from t
)
select id, user, points
from r
where rnk = 2;
If you want to strictly get only one row, corresponding to the second highest points, then my guess is that on ties you want the lowest id. In that case you can use the LIMIT function accordingly.
SELECT *
FROM tab
ORDER BY points DESC,
ID
LIMIT 1,1
The so written LIMIT clause will allow you to start limiting from the second row, then takes the first row available (which is the second one).
Check the demo here.

MySQL intertwine two queries based on previous query result

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?
192.168.1.1
google.com
facebook.com
twitter.com
192.168.1.2
facebook.com
twitter.com
...
...
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;
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 |
+-------------+--------------+--------------+-------------+
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.
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
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

sort on two columns

I have a table with site visits with the following columns:
timestamp
host
url
I would like to see the last few (say 200) visits but at the same time group visits of the same host together (to see the sequence of pages he/she visits).
If I do:
... SORT BY timestamp DESC, host
I get hosts mixed up if several visitors are online at the same time
If I do:
... SORT BY host, timestamp DESC
I do not get the latest visits (just the latest visits from each host)
I would like to see e.g.
9:01 | a.com | /index
9:05 | a.com | /interesting
9:07 | a.com | /contact
9:02 | b.com | /index
9:03 | b.com | /product-a
9:08 | b.com | /thanks-for-buying
Is that possible in Mysql or should I further process the result in php?
Try this::
Select *, MAX(timestamp_col) as lastVisit from site_table
GROUP BY HOSTS order by lastVisit desc
You can't do ORDER BY followed by LIMIT and then another ORDER BY, so you have to use a sub query:
SELECT * FROM (SELECT *
FROM visits
ORDER BY timestamp DESC
LIMIT 200
) visits2
ORDER BY host
You have to limit the result if you want the last 200
SORT BY timestamp DESC, host LIMIT 0, 200
And if you dont the same visitor to show up again , use
SELECT DISTINCT visitor FROM ....
I think it is not possible make normal in one query. You can try this:
SELECT *
FROM table AS t1
WHERE t1.timestamp_col >= (SELECT MIN(tstamp)
FROM (SELECT t2.timestamp_col
FROM tables AS t2
WHERE t2.host = t1.host
ORDER BY timestamp_col DESC
LIMIT 200
)
)
I don't test this crazy code... But I hope it give you way :)
The answers above pointed my in the right direction, thanks. This one works. The LIMIT 1000 is to reduce the query from almost 3 minutes to 7 seconds (40000 records).
SELECT v1.stamp, v1.host FROM visits AS v1
LEFT JOIN (SELECT MIN(date) AS firstVisit, host
FROM visitor AS v2
GROUP BY v2.host
ORDER BY firstVisit DESC
LIMIT 1000) AS j
ON v1.host=j.host
ORDER BY firstVisit DESC, v1.host, v1.date DESC
LIMIT 100;

Can I get the highest amount of a value in a mysql database?

I want to display the user with the most posts. the posts are added by counting how many times their username is displayed in the database. How can I grab all the elements and check to see which value appears more then others?
So say my database looks like this:
id | username
1 | test
2 | test
3 | no test
"test" is shown the most, so how could I say
highest poster: "test"
This query returns username and number of occurrences, sorted in reverse order, so the first record is the one with more occurrences:
select username, count(id) from tablename
group by username
order by count(id) desc
UPDATE:
As pointed by thedugas and Joe Phillips, you can add a limit 1 clause to this query to get only the record with the highest number of occurrences
select username, count(id) as uc
from tableName
group by username
order by uc desc
limit 1
SELECT username
FROM mytable
GROUP BY username
ORDER BY COUNT(1) DESC
LIMIT 1

MySQL top count({column}) with a limit

I have a table with an ip address column. I would like to find the top five addresses which are listed.
Right now I'm planning it out the following:
Select all distinct ip addresses
Loop through them all saying count(id) where IP='{ip}' and storing the count
List the top five counts.
Downsides include what if I have 500 ip addresses. That's 500 queries I have to run to figure out what are the top five.
I'd like to build a query like so
select ip from table where 1 order by count({distinct ip}) asc limit 5
select ip, count(*)
from table
group by ip
order by count(*) desc limit 5
select IP, count(IP) as IPCount from TABLE
group by IP
order by IPCount DESC
Limit 5
There is :)