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.
Related
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
How do I sort a table by it's minimum value per group but at the same time keep a group of rows together. Below a simple example of what i am trying to accomplish. The table is sorted by the lowest group value, but the group remains together. I am pretty sure this question has been asked already but i could not find an answer.
+---------+-------+
| Group | value |
+---------+-------+
| 1 | 3.99 |
| 1 | 10.99 |
| 3 | 12.69 |
| 1 | 20.95 |
| 2 | 19.95 |
| 3 | 10.09 |
+---------+-------+
Desired output
+---------+-------+
| Group | value |
+---------+-------+
| 1 | 3.99 |
| 1 | 10.99 |
| 1 | 20.95 |
| 3 | 10.69 |
| 3 | 12.09 |
| 2 | 19.95 |
+---------+-------+
If you are running MySQL 8.0, you can sort with window functions:
select t.*
from mytable t
order by min(value) over(partition by grp), value
In earlier versions, one option is to join an aggregate subquery:
select t.*
from mytable t
inner join (
select grp, min(value) min_value from mytable group by grp
) m on m.grp = t.grp
order by m.min_value, t.value
SELECT *,RN = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY VALUE,ID) FROM TEMP
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 ;
I have table with following structure and records.
table t1
+------+-------------+---------------------+
| name | f_inserted | timestamp |
+------+-------------+---------------------+
| AAA | 1 | 2012-04-10 06:44:19 |
| BBB | 0 | 2012-04-10 08:44:19 |
| AAA | 1 | 2012-04-10 09:44:19 |
| CCC | 1 | 2012-04-11 09:48:19 |
+------+-------------+---------------------+
I want to show unique date and count f_inserted where f_inserted = 1
In the folowing table I want the result as -
result
+-------------+------+
| date | cnt |
+-------------+------+
| 2012-04-10 | 2 |
| 2012-04-11 | 1 |
+------+------+------+
Thanks in advance !
This is a basic MySQL GROUP BY query. The only tricky part is that your timestamp has a DATETIME, and you only want a date. Use the DATE() function to convert.
SELECT date(`timestamp`) as `date`, COUNT(*) from t1
WHERE f_inserted = 1
GROUP BY date(`timestamp`)
This will give the exect result you wished for-
SELECT date(`timestamp`) as `date`,
COUNT(*) as cnt
from table_name
WHERE f_inserted = 1
GROUP BY date(`timestamp`)
order by cnt desc
How to select 1st, 2nd or 3rd value before MAX ?
usually we do it with order by and limit
SELECT * FROM table1
ORDER BY field1 DESC
LIMIT 2,1
but with my current query I don't know how to make it...
Sample table
+----+------+------+-------+
| id | name | type | count |
+----+------+------+-------+
| 1 | a | 1 | 2 |
| 2 | ab | 1 | 3 |
| 3 | abc | 1 | 1 |
| 4 | b | 2 | 7 |
| 5 | ba | 2 | 1 |
| 6 | cab | 3 | 9 |
+----+------+------+-------+
I'm taking name for each type with max count with this query
SELECT
`table1b`.`name`
FROM
(SELECT
`table1a`.`type`, MAX(`table1a`.`count`) AS `Count`
FROM
`table1` AS `table1a`
GROUP BY `table1a`.`type`) AS `table1a`
INNER JOIN
`table1` AS `table1b` ON (`table1b`.`type` = `table1a`.`type` AND `table1b`.`count` = `table1a`.`Count`)
and I want one more column additional to name with value before max(count)
so result should be
+------+------------+
| name | before_max |
+------+------------+
| ab | 2 |
| b | 1 |
| cab | NULL |
+------+------------+
Please ask if something isn't clear ;)
AS per your given table(test) structure, the query has to be as follows :
select max_name.name,before_max.count
from
(SELECT type,max(count) as max
FROM `test`
group by type) as type_max
join
(select type,name,count
from test
) as max_name on (type_max.type = max_name.type and count = type_max.max )
left join
(select type,count
from test as t1
where count != (select max(count) from test as t2 where t1.type = t2.type)
group by type
order by count desc) as before_max on(type_max.type = before_max .type)