How to select latest rank of item in mysql - mysql

I have two tables: coins and coin_history
coins table
|id | symbol | date |
+---+--------+----------+
|1 | BTC |01-02-2011|
|2 | ETH |21-02-2011|
|3 | XRP |08-01-2011|
|4 | BCH |25-01-2011|
coin_history table; rank of each coin on a date
|id | coin_id | rank | date |
+---+---------+--------+----------+
| 1 | 1 | 1 |01-02-2018|
| 2 | 1 | 1 |02-02-2018|
| 3 | 1 | 1 |04-02-2018|
| 4 | 2 | 2 |01-02-2018|
| 5 | 2 | 3 |02-02-2018|
| 6 | 2 | 2 |04-02-2018|
| 7 | 3 | 3 |01-02-2018|
| 8 | 3 | 2 |02-02-2018|
| 9 | 3 | 4 |04-02-2018|
|10 | 4 | 4 |01-02-2018|
|11 | 4 | 4 |02-02-2018|
|12 | 4 | 3 |04-02-2018|
I want to get each coin from coins ordered by latest rank from coin_history
something link this result:
|coin_id | symbol | rank |
+--------+--------+--------+
| 1 | BTC | 1 |
| 2 | ETH | 2 |
| 4 | BCH | 3 |
| 3 | XRP | 4 |
I've tried some queries but all of them result to this error
this is incompatible with sql_mode=only_full_group_by

In a Derived Table, get the Maximum value of date from the history for a particular coin.
Join this result-set with your main tables, to fetch only the row corresponding to recent date for a coin.
Eventually, use ORDER BY to get result in Ascending order for Rank.
Try:
SELECT
c.coin_id,
c.symbol,
ch.rank
FROM
coins AS c
JOIN
coin_history AS ch
ON ch.coin_id = c.coin_id
JOIN
(
SELECT coin_id,
MAX(date) AS max_date
FROM coin_history
GROUP BY coin_id
) AS dt
ON ch.coin_id = dt.coin_id AND
ch.date = dt.max_date
ORDER BY ch.rank

MySQL has a other more simple method but it is MySQL only, so don't use this when you need database portability in your code.
Using GROUP_CONCAT in combination with nested SUBSTRING_INDEX functions to get the first element/item can also be used to get a extra column which keeping the correct grouped information..
Note: SET SESSION group_concat_max_len = ##max_allowed_packet; is very important to use otherwise GROUP_CONCAT will only display 1024 bytes..
Query
SET SESSION group_concat_max_len = ##max_allowed_packet;
SELECT
coins.id AS coin_id
, coins.symbol
, CAST(
SUBSTRING_INDEX(
SUBSTRING_INDEX(
GROUP_CONCAT(coin_history.rank ORDER BY coin_history.date DESC)
, ','
, 1
)
, ','
, -1
) AS UNSIGNED) AS rank
FROM
coins
INNER JOIN
coin_history
ON
coins.id = coin_history.coin_id
GROUP BY
coins.id
, coins.symbol
ORDER BY
rank
Result
| coin_id | symbol | rank |
| ------- | ------ | ---- |
| 1 | BTC | 1 |
| 2 | ETH | 2 |
| 4 | BCH | 3 |
| 3 | XRP | 4 |
DB Fiddle demo

SELECT q.*from
(SELECT h.*, c.symbol
FROM `coin_history` AS h
JOIN coins AS c ON h.coin_id = c.id
ORDER BY h.date DESC
LIMIT 50) AS q
GROUP BY q.coin_id
ORDER BY q.rank ASC

Related

SQL query to group by day but with another condition

I have data something like this:
| visitor_id | time | my_flag |
| 1 | 01-01-2017 | 1 |
| 2 | 01-01-2017 | 1 |
| 1 | 01-02-2017 | 2 |
| 3 | 01-02-2017 | 2 |
etc...
I want to group all visitors in one day but based on a flag. The flag can have two values, 1 or 2. So I need something like
| 12 | 01-01-2017 | 1 |
| 10 | 01-01-2017 | 2 |
| 34 | 01-02-2017 | 1 |
I have
select v.visitor_id v.time, v.flag
from my_table as v
group by DAY(v.time) having flag=1;
But I am not able to figure out how to add multiple conditions (flag=1 and flag=2)? Any pointers?
try something like this
select v.visitor_id v.time, v.flag
from my_table as v
where v.flag in (1,2)
group by DAY(v.time), v.flag
SELECT v.time,
v.flag,
COUNT(v.visitor_id)
FROM my_table as v
GROUP BY v.time,
v.flag;`

SQL query that randoms the id from all posible ids in table and outputs the rows containing that id

I want a query that selects all rows that have the UploadedbyUserID = Rand() (selects random id from possible UploadbyUserID in this case 4, 3 and 22 and only those 3 not 2 nor 5)
And if the rand gives 4 it outputs this:
+------+------+------------+--------------------+
| id | name | date | UploadedbyUserID |
+------+------+------------+--------------------+
| 1 | 2222 | Testing | 4 |
| 2 | Jack | description| 4 |
| 6 | Zara | 2007-02-06 | 4 |
+------+------+------------+--------------------+
This is the whole table
+------+------+------------+--------------------+
| id | name | date | UploadedbyUserID |
+------+------+------------+--------------------+
| 1 | 2222 | Testing | 4 |
| 2 | Jack | description| 4 |
| 3 | ffdsd| 2007-05-06 | 4 |
| 4 | dsm | 2007-05-27 | 3 |
| 5 | dddd | 2007-04-06 | 3 |
| 6 | Zara | 2007-02-06 | 4 |
| 7 | John | 2007-01-24 | 22 |
+------+------+------------+--------------------+
and if it randomizes 3 it outputs this
+------+------+------------+--------------------+
| id | name | date | UploadedbyUserID |
+------+------+------------+--------------------+
| 4 | dsm | 2007-05-27 | 3 |
| 5 | dddd | 2007-04-06 | 3 |
+------+------+------------+--------------------+
Ask if you need more information
Hmmm. This is one way:
select t.*
from (select uploadedbyuserid
from t
order by rand()
limit 1
) u join
t
using (uploadedbyuserid);
First, let me say that this is weighted by the number of times that a user has uploaded something. So, user "4" would appear a bit more often than "3", in your example. If this is an issue:
select t.*
from (select uploadedbyuserid
from (select distinct uploadedbyuserid from t) t
order by rand()
limit 1
) u join
t
using (uploadedbyuserid);
The next observation is that this can be compute intensive. If you have lots of rows, there are various ways to speed these up. For instance, one simple method would be to get about 1 out of 10000 rows:
select t.*
from (select uploadedbyuserid
from (select distinct uploadedbyuserid
from t
) t
where rand() < 0.001
order by rand()
limit 1
) u join
t
using (uploadedbyuserid);

Select most recent MAX() and MIN() - WebSQL

i'm build an exercises web app and i'm working with two tables like this:
Table 1: weekly_stats
| id | code | type | date | time |
|----|--------------|--------------------|------------|----------|
| 1 | CC | 1 | 2015-02-04 | 19:15:00 |
| 2 | CC | 2 | 2015-01-28 | 19:15:00 |
| 3 | CPC | 1 | 2015-01-26 | 19:15:00 |
| 4 | CPC | 1 | 2015-01-25 | 19:15:00 |
| 5 | CP | 1 | 2015-01-24 | 19:15:00 |
| 6 | CC | 1 | 2015-01-23 | 19:15:00 |
| .. | ... | ... | ... | ... |
Table 2: global_stats
| id | exercise_number |correct | wrong |
|----|-----------------|--------|-----------|
| 1 | 138 | 1 | 0 |
| 2 | 246 | 1 | 0 |
| 3 | 988 | 1 | 10 |
| 4 | 13 | 5 | 0 |
| 5 | 5 | 4 | 7 |
| 6 | 5 | 4 | 7 |
| .. | ... | ... | ... |
What i would like is to get MAX(correct-wrong) and MIN(correct-wrong) and now i'm working with this query:
SELECT
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MAX(correct - wrong) from global_stats)
UNION
SELECT
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MIN(correct - wrong) from global_stats);
This query is working good, except for one thing: when "WHERE correct - wrong = (SELECT MIN(correct - wrong)[...]" selects more than one row, the row selected is the first but i would like to have returned the most recent (in other words: ordered by datetime(date, time)). Is it possible?
Thanks!
I think you can solve it like this:
SELECT * FROM (
SELECT
1 as sort_column,
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MAX(correct - wrong) from global_stats)
ORDER BY date DESC, time DESC
LIMIT 1 ) as a
UNION
SELECT * FROM (
SELECT
2 as sort_column,
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MIN(correct - wrong) from global_stats)
ORDER BY date DESC, time DESC
LIMIT 1) as b
ORDER BY sort_column;
Here is the documentation about how UNION works.

How to find duplicate rows with SQL- GROUP BY

I've a table
+----+------------+
| id | day |
+----+------------+
| 1 | 2006-10-08 |
| 2 | 2006-10-08 |
| 3 | 2006-10-09 |
| 4 | 2006-10-09 |
| 5 | 2006-10-09 |
| 5 | 2006-10-09 |
| 6 | 2006-10-10 |
| 7 | 2006-10-10 |
| 8 | 2006-10-10 |
| 9 | 2006-10-10 |
+----+------------
I want to group by the frequency and its count, for eg:-
Since there's a date 2006-10-08 that appears twice, hence frequency 2 and there is only one date that appears twice , hence total dates 1.
Another eg:-
2006-10-10 and 2006-10-09 both appears 4 times, hence frequency 4 and total dates with frequency 4 are 2.
Following is the expected output.
+----------+--------------------------------+
| Freuency | Total Dates with frequency N |
+----------+--------------------------------+
| 1 | 0 |
| 2 | 1 |
| 3 | 0 |
| 4 | 2 |
+----------+--------------------------------+ and so on till the maximum frequency.
What I've tried is the following:-
select day, count(*) from test GROUP BY day;
It returns the frequency of each date, ie
+------------+----------+
| day | count(*) |
+------------+----------+
| 2006-10-08 | 2 |
| 2006-10-09 | 4 |
| 2006-10-09 | 4 |
+------------+----------+
Please help with the above problem.
Just use your query as a subquery:
select freq, count(*)
from (select day, count(*) as freq
from test
group by day
) d
group by freq;
If you want to get the 0 values, then you have to work harder. A numbers table is handy (if you have one) or you can do:
select n.freq, count(d.day)
from (select 1 as freq union all select 2 union all select 3 union all select 4
) n left join
(select day, count(*) as freq
from test
group by day
) d
on n.freq = d.freq
group by n.freq;

Order and group by date in Mysql

Hi all and thanks in advance.
I have a small problem which can not resolve, I have this table, and I want to sort by date and group it (but I only show 1 row per idCAT)
| id | idcat | name | date |
| 1 | 3 | xx | 2011-01-02 |
| 2 | 4 | xf | 2011-01-02 |
| 3 | 3 | cd | 2011-01-01 |
| 4 | 1 | cg | 2011-01-04 |
| 5 | 4 | ce | 2011-01-06 |
would like to stay that way, try in a way but I can not
| 2 | 4 | xf | 2011-01-02 |
| 3 | 3 | cd | 2011-01-01 |
| 4 | 1 | cg | 2011-01-04 |
Order by ID
Thank's a one friend the work.
SELECT id, idcat, name, date FROM (SELECT * FROM data ORDER BY idcat, date ) m GROUP BY idcat
I can't test conveniently atm, but try this:
SELECT FIRST(id), idcat, FIRST(name), FIRST(date) AS d FROM myTable GROUP BY idcat ORDER BY d;
Note the use of the FIRST calls to pick the first row in the table with any particular idcat.
If you are trying to get groupings by the idcat, then sorted by date:
select id, idcat, name, date from myTable group by idcat order by date;