SQL with specific LIMIT - mysql

I have the next example table:
id | user_id | data
-------------------
1 | 1 | 10
2 | 2 | 10
3 | 2 | 10
4 | 1 | 10
5 | 3 | 10
6 | 4 | 10
7 | 4 | 10
8 | 5 | 10
9 | 5 | 10
10 | 2 | 10
11 | 6 | 10
12 | 3 | 10
13 | 1 | 10
I need to create a SELECT query, that LIMITS my data. For example, I have a limit range (1, 3) (page number = 1, row count = 3). It should selects rows with first 3 unique user_id. And if there are some rows in the end of table with this first user_id's, they should be included to the result. LIMIT statement is bad for this query, because I can get more than 3 rows. Output for my limit should be:
id | user_id | data
-------------------
1 | 1 | 10
2 | 2 | 10
3 | 2 | 10
4 | 1 | 10
5 | 3 | 10
10 | 2 | 10
12 | 3 | 10
13 | 1 | 10
Can you help me to generate this query?

How about:
SELECT *
FROM table
WHERE user_id IN
(SELECT distinct(user_id) FROM table order by user_id LIMIT 3);

What about something like this?
SELECT * FROM table WHERE user_id BETWEEN (number) AND (number+row count)
I know it isn't working but you should be able to make it work ^^

The sample code below can be used for Oracle & Mysql. (use TOP for SQL Server & Sybase)
You get all the results from your table (t1) that match the top 3 user_id (t2) (check the MySQL manual for the limit function)
SELECT *
FROM exampletable t1
INNER JOIN (
SELECT DISTINCT user_id
FROM exampletable
ORDER BY user_id
LIMIT 0,3 -- this is the important part
) AS t2 ON t1.user_id = t2.user_id
ORDER BY id
For the next 3 id's change the limit 0,3 to limit 3,6.

Related

Random record from the table

I have customer table with 10 columns. In the table customer id is repeated. I need to take only one record every customer but randomly.
Let suppose customer table contain total 10000 records. But distinct customers is only 500.
So i need only 500 distinct customer data randomly.
I am using mysql 5.7.
Consider the following...
SELECT * FROM my_table;
+----+-------------+
| id | customer_id |
+----+-------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 3 |
| 4 | 5 |
| 5 | 3 |
| 6 | 2 |
| 7 | 1 |
| 8 | 4 |
| 9 | 5 |
| 10 | 2 |
| 11 | 3 |
| 12 | 1 |
| 13 | 4 |
+----+-------------+
SELECT id
, customer_id
FROM
( SELECT id
, customer_id
, CASE WHEN #prev=customer_id THEN #i:=#i+1 ELSE #i:=1 END i
, #prev:=customer_id
FROM
( SELECT id
, customer_id
FROM my_table
ORDER
BY customer_id
, RAND()
) x
JOIN (SELECT #prev:=null,#i:=0) vars
) n
WHERE i = 1
ORDER
BY customer_id;
-- sample output, different each time --
+----+-------------+
| id | customer_id |
+----+-------------+
| 12 | 1 |
| 10 | 2 |
| 3 | 3 |
| 8 | 4 |
| 9 | 5 |
+----+-------------+
You do not want to ORDER BY RAND() because that will be extremely slow for a large table because it will actually sort all of those random records.
Instead pick a random int less than the number of rows in the table (random_num_less_than_row_count) and do this which is faster but not perfect.
SELECT * FROM atable LIMIT $random_num_less_than_row_count, 1
Or if u have a primary key that is an auto_increment you can pick a random int less than the highest id in the table (random_num_less_than_last_id) do the following which is pretty fast.
SELECT * FROM atable WHERE id >= $random_num_less_than_last_id ORDER BY id ASC LIMIT 1
I did a >= and an ORDER BY id ASC so that if you are missing ids you'll still get a result. But if you have many large gaps you need the slower first option above.
Not sure about it but it is a beginner level query which might to get the desired result
SELECT Distinct column FROM table
ORDER BY RAND()
LIMIT 500
PS: This code isn't in mysql 5.7. And if anyone have a better query more than happy to get corrected

How to find to "opposite" records on MySQL?

I have 1 table with the following cols:
giver_id | receiver_id
10 | 12
9 | 10
10 | 20
12 | 10
I am looking for a mysql query that will return 10-12 / 12-10 as a match.
Thanks
To identify the records for which an "opposite" record exist, you could do:
SELECT *
FROM mytable t
WHERE EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.giver_id = t.receiver_id AND t.giver_id = t1.receiver_id
)
This demo on DB Fiddle with your sample data returns:
| giver_id | receiver_id |
| -------- | ----------- |
| 10 | 12 |
| 12 | 10 |

mysql condition in a select

My table:
id | elite | pos
1 | 0 | 9
2 | 1 | 8
3 | 0 | 7
4 | 1 | 6
5 | 0 | 5
6 | 1 | 4
7 | 0 | 3
8 | 1 | 2
9 | 0 | 1
10 | 1 | 0
I have this simple query
SELECT id, elite FROM tbl LIMIT 0, 5 ORDER BY pos DESC
It will return the id 1 2 3 4 5. Over time, these values were to change. The result must have always a count of 5, however if on the result there are at least one id with an elite >= 1, the result must not contain any more id with an elite having the 1 value. So the result must not contain id having more than one elite >= 1.
Is this possible within a query?
You can use UNION to combine two queries, like so:
(SELECT * FROM tbl WHERE elite = 1 LIMIT 1)
UNION
(SELECT * FROM tbl WHERE elite = 0)
ORDER BY pos DESC LIMIT 5
It will give the results you need.
Check out Mysql reference for UNIONs

Remove duplicates from one column keeping whole rows

id | userid | total_points_spent
1 | 1 | 10
2 | 2 | 15
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
With the above table, I would first like to remove duplicates of userid keeping the rows with the largest total_points_spent, like so:
id | userid | total_points_spent
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
And then I would like to sum the values of total_points_spent, which would be the easy part, resulting in 70.
I am not really sure the "remove" you meant is to delete or to select. Here is the query for select only max totalpointspend record respectively.
SELECT tblA.*
FROM ( SELECT userid, MAX(totalpointspend) AS maxtotal
FROM tblA
GROUP BY userid ) AS dt
INNER JOIN tblA
ON tblA.userid = dt.userid
AND tblA.totalpointspend = dt.maxtotal
ORDER BY tblA.userid

MySQL Update Sorted Number

I have MYSQL data like this
id | number
1 | 3
4 | 4
7 | 7
10 | 5
11 | 6
I have the database like that, and how to update the number so it will be sorted incremental?
Which mean the result will be like this
id | number
1 | 1
4 | 2
7 | 3
10 | 4
11 | 5
i updated the question so there will be no confusion in id and since id will be not consecutive
set #val = 0;
update table_name set number = (#val:=#val+1);
This would work even if table is:
id | number
1 | 3
4 | 4
7 | NULL
10 | 5
11 | NULL
to be like this:
id | number
1 | 1
4 | 2
7 | 3
10 | 4
11 | 5
update table set number=id where 1
Try this:
SET #idrank = 0;
SET #numrank = 0;
UPDATE
tbl a
INNER JOIN
(
SELECT id, #idrank:=#idrank+1 AS id_rank
FROM tbl
ORDER BY id
) b ON a.id = b.id
INNER JOIN
(
SELECT number, #numrank:=#numrank+1 AS number_rank
FROM tbl
ORDER BY number
) c ON b.id_rank = c.number_rank
SET
a.number = c.number;
This will account for gaps and irregularities in the number field as well as duplicates. Say the entire data set was something like:
id | number
---------------
2 | 534
3 | 421
6 | 2038
7 | 41
10 | 5383
11 | 5
12 | 933
15 | 43
The resulting table set after the update will be:
id | number
---------------
2 | 5
3 | 41
6 | 43
7 | 421
10 | 534
11 | 933
12 | 2038
15 | 5383
Explanation:
It basically takes the ascending ranks of each field separately and joins on the ranks so that the ordered id is matched up with corresponding ordered number.
The first INNER JOIN subselect will look like this:
id | id_rank
---------------
2 | 1
3 | 2
6 | 3
7 | 4
10 | 5
11 | 6
12 | 7
15 | 8
Then the second INNER JOIN subselect will like this:
number | number_rank
---------------
534 | 5
421 | 4
2038 | 7
41 | 2
5383 | 8
5 | 1
933 | 6
43 | 3
Then when you join the two subselects on id_rank = number_rank, you line the ascending order of the two fields up. Once you have that, updating becomes a simple matter of setting the table's number = the second joined table's number.