Mysql DISTINCT account_id and ORDER BY - mysql

I want to select the last (datetime) record_version ordered by datetime DESC, for every account_id
SELECT *
FROM `record_versions`
WHERE record_id='26'
GROUP BY `account_id`
ORDER BY datetime DESC
It returns only one record for account_id, but it's not the last

You can use a self join to get your desired result ,inner query will get maximum of your datetime column per account_id and it will join the rows from outer query with the latest datetime value
SELECT
r.*
FROM
`record_versions` r
JOIN
(SELECT
MAX(`datetime`) `datetime`,
account_id
FROM
record_versions
GROUP BY account_id) t
ON (
r.account_id = t.account_id
AND r.datetime = t.datetime
)
WHERE r.record_id = '26'

Related

MySQL group by only on specific amount of records (query inside JOIN expression)

I have a History table that represents messages that are stored by some sort of chat program.
It has a user id, message & datetime. (specified on: http://sqlfiddle.com/#!9/49fcefb/5)
Now, what I want is to have a result which contains:
The max amount of messages typed by date
What user has the most messages and howmany messages this user typed)
I got it working, but I find the query rather slow, I think its because of the last GROUP BY (GROUP BY b.cnt) as this will group over all the records found.
Query:
SELECT b.cnt as dayCount, a.cnt as userCount, a.userid as userId, b.date
FROM (
select date_added as date, user_id as userid, count(*) as cnt from history group by userid, day(date_added),month(date_added),year(date_added)
) a
INNER JOIN (
select date_added as date, count(*) as cnt from history group by day(date_added),month(date_added),year(date_added)
) b ON year(a.date) = year(b.date)
AND month(a.date) = month(b.date)
AND day(a.date) = day(b.date)
GROUP BY b.cnt
ORDER BY dayCount desc, userCount desc limit 10;
Can someone advice me on how to solve this? Maybe with another sort of query?
Thanks in advance!
You can try using windows function with Subquery to get the same result.
select SQ.daycount,SQ.usercount,SQ.user_id, SQ.date1 from (
select sum(count(Message)) over (partition by date(date_added)) as daycount, --to get max amount of msg by date
max(count(Message)) over (partition by date(date_added)) as maxuser, -- to identify user with most msg
count(Message) as usercount,
date(date_added) as date1,user_id from history
group by date1,user_id ) SQ
where SQ.usercount=SQ.maxuser
Check the Fiddle here
seems you are joining with wrong criteria.
first table is getting the # of users, 2nd table is getting the #of days per user_id. see dbfiddle
SELECT b.cnt as dayCount, a.cnt as userCount, a.userid as userId, b.date
FROM (
select
user_id as userid
, count(*) as cnt
from history
group by userid
) a
LEFT JOIN (
select cast(date_added as date) as date
, count(*) as cnt
, user_id as userid
from history
group by cast(date_added as date)
) b ON a.userid = b.userid
ORDER BY dayCount desc, userCount desc limit 10;

Mysql Group By get latest record with Count

This is my customer table.
I want to group by emp_id alongwith the count. But Group By gets the 'first' record and not the 'newest' one.
I have tried various queries, like this
SELECT id, emp_id, COUNT( * ) AS count, created_at
FROM customer c
WHERE created_at = (
SELECT MAX( created_at )
FROM customer c2
WHERE c2.emp_id = c.emp_id
)
GROUP BY emp_id
ORDER BY created_at DESC
LIMIT 0 , 30
But cannot get the count. Please help.
Edit: this answer doesn't help to obtain count
Try joining to a subquery:
SELECT c1.id, c1.emp_id, c1.created_at, c2.cnt
FROM customer c1
INNER JOIN
(
SELECT emp_id, MAX(created_at) AS max_created_at, COUNT(*) AS cnt
FROM customer
GROUP BY emp_id
) c2
ON c1.emp_id = c2.emp_id AND c1.created_at = c2.max_created_at;
please try this
SELECT cust1.id, cust1.emp_id, cust1.created_at, cust2.cnt
FROM customer cust1
INNER JOIN
(
SELECT emp_id, MAX(created_at) AS max_created_at, COUNT(*) AS count
FROM customer
GROUP BY emp_id
) cust2
ON cust1.emp_id = cust2.emp_id AND cust1.created_at = cust2.max_created_at;

MySQL SELECT subquery

I have a calendar and user_result table and I need to join these two queries.
calendar query
SELECT `week`, `date`, `time`, COUNT(*) as count
FROM `calendar`
WHERE `week` = 1
GROUP BY `date`
ORDER BY `date` DESC
and the result is
{"week":"1","date":"2014-08-21","time":"15:30:00","count":"4"}, {"week":"1","date":"2014-08-20","time":"17:30:00","count":"12"}
user_result query
SELECT `date`, SUM(`point`) as score
FROM `user_result`
WHERE `user_id` = 1
AND `date` = '2014-08-20'
and the result is just score 3
My goal is to always show calendar even if the user isn't present in the user_result table, but if he is, SUM his points for that day where calendar.date = user_result.date. Result should be:
{"week":"1","date":"2014-08-21","time":"15:30:00","count":"4","score":"3"}, {"week":"1","date":"2014-08-20","time":"17:30:00","count":"12","score":"0"}
I have tried this query below, but the result is just one row and unexpected count
SELECT c.`week`, c.`date`, c.`time`, COUNT(*) as count, SUM(p.`point`) as score
FROM `calendar` c
INNER JOIN `user_result` p ON c.`date` = p.`date`
WHERE c.`week` = 1
AND p.`user_id` = 1
GROUP BY c.`date`
ORDER BY c.`date` DESC
{"week":"1","date":"2014-08-20","time":"17:30:00","count":"4","score":"9"}
SQL Fiddle
ow sorry, i was edited, and i was try at your sqlfiddle, if you want to show all date from calendar you can use LEFT JOIN, but if you want to show just the same date between calendar and result you can use INNER JOIN, note: in this case INNER JOIN just show 1 result, and LEFT JOIN show 2 results
SELECT c.`week`, p.user_id, c.`date`, c.`time`, COUNT(*) as count, p.score
FROM `calendar` c
LEFT JOIN
(
SELECT `date`, SUM(`point`) score, user_id
FROM `result`
group by `date`
) p ON c.`date` = p.`date`
WHERE c.`week` = 1
GROUP BY c.`date`
ORDER BY c.`date` DESC
I put a pre-aggreate query / group by date as a select for the one person you were interested in... then did a left-join to it. Also, your column names of week, date and time (IMO) are poor choice column names as they can appear to be too close to reserved keywords in MySQL. They are not, but could be confusing..
SELECT
c.week,
c.date,
c.time,
coalesce( OnePerson.PointEntries, 0 ) as count,
coalesce( OnePerson.totPoints, 0 ) as score
FROM
calendar c
LEFT JOIN ( select
r.week,
r.date,
COUNT(*) as PointEntries,
SUM( r.point ) as totPoints
from
result r
where
r.week = 1
AND r.user_id = 1
group by
r.week,
r.date ) OnePerson
ON c.week = OnePerson.week
AND c.date = OnePerson.date
WHERE
c.week = 1
GROUP BY
c.date
ORDER BY
c.date DESC
Posted code to SQLFiddle

MySQL group by last entry

My table payment_status have these fields:
id
payment_id
status
created
created_by
Many entries could have the same payment_id... So, I want to get the last status for one payment_id...
I have this request that work but take too much time to load... I would like to have an optimize version to group by payment_id and take the last status.
SELECT pstatus.*
FROM `payment_status` AS pstatus
WHERE pstatus.id = (
SELECT id
FROM `payment_status`
WHERE pstatus.status = '200'
ORDER BY created DESC
LIMIT 1
)
GROUP BY pstatus.payment_id
ORDER BY pstatus.payment_id DESC
Try this query -
SELECT t1.* FROM payment_status t1
JOIN (SELECT payment_id, MAX(created) max_created
FROM payment_status
GROUP BY payment_id
) t2
ON t1.payment_id = t2.payment_id AND t1.created = t2.max_created;
...then add WHERE conditions you need.
Try to use JOIN:
SELECT p1.*
FROM payment_status p1
INNER JOIN
(
SELECT id, MAX(created) MaxCreated
FROM payment_status
WHERE status = '200'
GROUP BY id
) p2 ON p1.id = p2.id AND p1.created = p2.MaxCreated
ORDER BY p1.payment_id DESC
this should work
SELECT *
FROM payment_status
WHERE status = '200'
ORDER BY created DESC
LIMIT 1
shouldn't yo ujust be able to do this?:
(assuming that created is the timestamp, so "last" = "most recent")
SELECT pstatus.*
FROM `payment_status` AS pstatus
GROUP BY pstatus.payment_id, pstatus.status
ORDER BY pstatus.payment_id DESC, pstatus.created DESC
each row returns should have the payment_id with the most recent status.
I suppose you are using MySQL database.
Here I have a solution is fast and readable:
select
substring_index(
group_concat(status order by created desc)
, ',', 1
) as status_latest
from payment_status
group by payment_id
I'm quite sure it's fast than others SQL statement,
You may try it.

SELECT max(Date) rows BEFORE running WHERE clause?

I have this query that echoes all rows prior a particular date.
SELECT MAX(h.date), h.url
FROM HISTORY h
WHERE h.uid = '19'
AND h.date < (SELECT MAX(t.date)
FROM History t
WHERE t.url = 'canabalt.com'
AND t.uid = '19')
GROUP BY h.url
ORDER BY MAX(h.date) DESC
My problem is that I must only select rows that have max(Date).
But the where clause eliminates a number of rows that may have the max(Date) row and then looks for max(Date) in the remaining fields.
How can I first SELECT max(Date) and only afterwards run the WHERE clauses.
Try placing your criteria in the Having clause which is processed after the Group By clause.
Select Url, Max(Date) As MaxDate
From History
Where UID = '19'
Group By Url
Having Max( Date ) < (
Select Max( H1.Date )
From History As H1
Where H1.URL = 'canabalt.com'
And H1.UID = '19'
)
Order By Max( Date ) Desc