How to select last row for specific user? - mysql

I have a table like this:
// requests
+----+----------+-------------+
| id | id_user | unix_time |
+----+----------+-------------+
| 1 | 2353 | 1339412843 |
| 2 | 2353 | 1339412864 |
| 3 | 5462 | 1339412894 |
| 4 | 3422 | 1339412899 |
| 5 | 3422 | 1339412906 |
| 6 | 2353 | 1339412906 |
| 7 | 7785 | 1339412951 |
| 8 | 2353 | 1339413640 |
| 9 | 5462 | 1339413621 |
| 10 | 5462 | 1339414490 |
| 11 | 2353 | 1339414923 |
| 12 | 2353 | 1339419901 |
| 13 | 8007 | 1339424860 |
| 14 | 7785 | 1339424822 |
| 15 | 2353 | 1339424902 |
| 16 | 2353 | 1466272801 |
| 17 | 2353 | 1466272805 |
+----+----------+-------------+
I'm trying to get last row which is related to specific user. For example for this user id_user = 7785 I want to select this row:
| 14 | 7785 | 1339424822 |
And here is my query:
SELECT unix_time AS last_seen
FROM requests WHERE id = '7785'
ORDER BY unix_time DESC
LIMIT 1
But my query doesn't select any row. What's wrong?
SQL fiddle
Also as a note, can you please tell me should I create single index on id_user and uinx_time or should I create a multiple columns index on those two columns (id_user, unix_time)?

You are using the wrong column (id instead of id_user — or vice versa):
SELECT unix_time AS last_seen
FROM requests WHERE id_user = '7785'
ORDER BY unix_time DESC
LIMIT 1

Let a sub-query return each id_user with it's highest unix_time. Join with that result.
select t1.*
from tablename t1
join (select id_user, max(unix_time) as unix_time
from tablename
group by id_user) t2
on t1.id_user = t2.id_user and t1.unix_time = t2.unix_time
Will return all users and their latest login.
Add WHERE id_user = '7785' if info about a single user is wanted.

In the WHERE condition you are comparing id with id of id_user.
Your mistake is at line two, it should be like:
SELECT unix_time AS last_seen
FROM requests WHERE id_user = '7785'
ORDER BY unix_time DESC
LIMIT 1

You have:
WHERE id = '7785'
If you want the row: | 7 | 7785 | 1339412951 |
You need something like:
SELECT TOP 1 unix_time AS last_seen
FROM requests WHERE id_user = '7785'
ORDER BY unix_time DESC
This will take the top result of the query where the user_ID equals '7785'. The 'ORDER BY unix_time DESC' puts the values with the highest unit time at the top so it will by the last request that user has had.

You can use below query it will help you
SELECT SUBSTRING_INDEX(id,',',1) AS id ,SUBSTRING_INDEX(id_user,',',1) AS id_user, unix_time FROM
(SELECT GROUP_CONCAT(id ORDER BY unix_time DESC ) AS id, GROUP_CONCAT(id_user ORDER BY unix_time DESC ) AS id_user ,MAX(unix_time) AS unix_time FROM test_71 GROUP BY id_user
HAVING id_user='7785' ) t ;

Related

How to select one row per user conditionally?

I have the following query:
select count(1) num, business_id, user_id FROM `pos_transactions`
group by user_id, business_id
order by user_id
It returns this:
+--------+-------------+---------+
| num | business_id | user_id |
+--------+-------------+---------+
| 3 | 503 | 12 |
| 7 | 33 | 12 |
| 1 | 771 | 13 |
| 2 | 86 | 13 |
| 1 | 772 | 13 |
| 4 | 652 | 14 |
| 4 | 567 | 14 |
+--------+-------------+---------+
I need to select only one row per user_id, the one which has a bigger num value. If all num values for a user are identical, then just one of them should be selected randomly (i.e. user #14). So, here is the expected result:
+--------+-------------+---------+
| num | business_id | user_id |
+--------+-------------+---------+
| 7 | 33 | 12 |
| 2 | 86 | 13 |
| 4 | 567 | 14 |
+--------+-------------+---------+
Any idea how can I do that?
I guess the solution will be something related to limit 1 per user. But I have no idea how I should write the query.
All I want to do is making the table unique per user_id, and the logic is selecting rows that have bigger num.
Use MAX() and FIRST_VALUE() window functions:
SELECT DISTINCT
MAX(COUNT(*)) OVER (PARTITION BY user_id) num,
FIRST_VALUE(business_id) OVER (PARTITION BY user_id ORDER BY COUNT(*) DESC) business_id,
user_id
FROM pos_transactions
GROUP BY user_id, business_id
ORDER BY user_id

sort data by specific order sequence (mysql)

So, let say I have this data
id | value | group
1 | 100 | A
2 | 120 | A
3 | 150 | B
4 | 170 | B
I want to sort it so it become like this
id | value | group
1 | 100 | A
3 | 150 | B
2 | 120 | A
4 | 170 | B
there will be more group than that, so if I the data ordered the group like (A,C,B,D,B,C,A), it will become (A,B,C,D,A,B,C)
You can add a counter column to the table, which will be used to sort the table:
select t.id, t.value, t.`group`
from (
select t.id, t.value, t.`group`,
(select count(*) from tablename
where `group` = t.`group` and id < t.id) counter
from tablename t
) t
order by t.counter, t.`group`
See the demo.
Results:
| id | value | group |
| --- | ----- | ----- |
| 1 | 100 | A |
| 3 | 150 | B |
| 2 | 120 | A |
| 4 | 170 | B |
You can approach this as
SELECT *
FROM `tablename`
ORDER BY
row_number() OVER (PARTITION BY `group` ORDER BY `group`), `group`

GROUP and ORDER Mysql get diffrent data in column

this is all data from current table
SELECT
id,harga,kode_tahun_ajaran
FROM
tblharga
+----+---------+-------------------+
| id | harga | kode_tahun_ajaran |
+----+---------+-------------------+
| 1 | 400000 | THN2018/2019 |
| 2 | 50000 | THN2018/2019 |
| 3 | 1000000 | THN2018/2019 |
| 4 | 900000 | THN2018/2019 |
| 5 | 500000 | THN2017/2018 |
| 6 | 600000 | THN2018/2019 |
+----+---------+-------------------+
and i run this code to get the last harga with grouping the kode_tahun_ajaran
SELECT
id,harga,kode_tahun_ajaran
FROM
tblharga
GROUP BY
kode_tahun_ajaran
ORDER BY id DESC
+----+--------+-------------------+
| id | harga | kode_tahun_ajaran |
+----+--------+-------------------+
| 5 | 500000 | THN2017/2018 |
| 1 | 400000 | THN2018/2019 |
+----+--------+-------------------+
the harga column should take the last data which is 600000 because of the order by code.
how can I retrieve the latest data by grouping it another way?
thanks in advance.
You can try below
SELECT
id,harga,kode_tahun_ajaran
FROM
tblharga where id in (select max(id) from tblharga group by kode_tahun_ajaran)
select id,S.kode_tahun_ajaran,harga
from tblharga S inner join
( select kode_tahun_ajaran,max(id) maxid from tblharga group by kode_tahun_ajaran) T
where T.kode_tahun_ajaran=S.kode_tahun_ajaran and maxid=id;

How to get greatest time when there is an aggregate function?

I have a table like this:
// mytable
+----+------+-------+-------------+
| id | type | score | unix_time |
+----+------+-------+-------------+
| 1 | 1 | 5 | 1463508841 | -- this (current output)
| 2 | 1 | 10 | 1463508842 |
| 3 | 2 | 5 | 1463508843 | -- this (current output)
| 4 | 1 | 5 | 1463508844 |
| 5 | 2 | 15 | 1463508845 | -- this (expected output)
| 6 | 1 | 10 | 1463508846 | -- this (expected output)
+----+------+-------+-------------+
And here is my query:
SELECT SUM(score), unix_time
FROM mytable
WHERE 1
GROUP BY type
And this is current output:
+-------+-------------+
| score | unix_time |
+-------+-------------+
| 30 | 1463508841 |
| 20 | 1463508843 |
+-------+-------------+
As you see, the output is containing the first row's unix_time. But I'm trying to select greatest one.
So here is expected output:
+-------+-------------+
| score | unix_time |
+-------+-------------+
| 30 | 1463508846 |
| 20 | 1463508845 |
+-------+-------------+
How can I do that?
I think you need sum(score) and max(unix_time) for the grouped value
SELECT type, SUM(score), max(unix_time)
FROM mytable
GROUP BY type
I omitted where 1 because seems non sense ..
Get the max time and total for each type and join on type.
select tm.maxtime,tot.total
from (select max(unixtime) maxtime, type
from mytable
group by type) tm
join (SELECT SUM(score) total, type
FROM mytable
GROUP BY type) tot
on tot.type = tm.type
or simply
select max(unixtime) maxtime, sum(score) total
from mytable
group by type
I think you just want max():
SELECT SUM(score), MAX(unix_time)
FROM mytable
WHERE 1
GROUP BY type;
MySQL is pretty much the only database that accepts your version of the query. You should be getting an error, because unix_time is not in the GROUP BY and not an argument to an aggregation function.

what will be the simple mysql query for this

I want to get the customer info where customer id should be 2 and the log_id should be maximum value
i tried below query but it is fetching first record found.
What will be the simple query
mysql> select * from log_customer where customer_id =2 group by customer_id having max(log_id);
+--------+------------+-------------+---------------------+-----------+----------+
| log_id | visitor_id | customer_id | login_at | logout_at | store_id |
+--------+------------+-------------+---------------------+-----------+----------+
| 2 | 56 | 2 | 2010-02-19 19:34:45 | NULL | 1 |
+--------+------------+-------------+---------------------+-----------+----------+
1 row in set (0.00 sec)
mysql> select * from log_customer where customer_id =2 limit 5;
+--------+------------+-------------+---------------------+---------------------+----------+
| log_id | visitor_id | customer_id | login_at | logout_at | store_id |
+--------+------------+-------------+---------------------+---------------------+----------+
| 2 | 56 | 2 | 2010-02-19 19:34:45 | NULL | 1 |
| 3 | 114 | 2 | 2010-02-23 17:31:55 | NULL | 1 |
| 31 | 1854 | 2 | 2010-03-08 18:31:28 | 2010-03-08 18:56:49 | 1 |
| 32 | 1992 | 2 | 2010-03-09 01:12:43 | NULL | 1 |
| 33 | 2304 | 2 | 2010-03-09 14:42:39 | NULL | 1 |
+--------+------------+-------------+---------------------+---------------------+----------+
Please do not suggest order by log_id desc I don't want to get in this way
SELECT *
FROM log_customer
WHERE customer_id = 2
AND log_id = (Select Max(Log_id)
FROM log_Customer
WHERE customer_id = 2)
That should do the trick
Edit without the Where:
SELECT *
FROM log_customer
WHERE log_id = (Select Max(Log_id)
FROM log_Customer
WHERE customer_id = 2)
Maybe this way:
SELECT *
FROM Log_Customer
WHERE Customer_Id = 2
AND Log_Id = (SELECT Max(Log_Id)
FROM Log_Customer
WHERE Customer_Id = 2)
A sub-select usually isn't bad as far as the execution plan is concerned.
select * from log_customer
left join
(select max(log_id) as max_id from log_customer where customer_id=2)
as log_customer2
on log_customer.log_id=log_customer2.max_id
where log_customer.customer_id=2;
oh damn...
select * from log_customer where customer_id=2 order by log_id desc limit 1;