I have a social network I am coding but it's a bit different than others, in this case there is only ever one status show per user on a feed section.
So I need to sort the status by date with the latest ones on top but also group by the userID
unfortunately I can't seem to get this working....
This is my current query:
SELECT *
FROM status
WHERE userID != "83" #This is just so my statuses don't show
GROUP BY userID
ORDER BY addedDate DESC
LIMIT 10
I expect to see the latest status results and only one per user instead I see the first statuses so the group by is working but not the order by.
Thanks in advance.
As mentioned in the comments to Robin's answer, that approach is unreliable because MySQL does not guarantee that it will always return the most recent status from each group. You must instead join your table with a subquery that selects the most recent status (based on addedDate).
SELECT *
FROM status
NATURAL JOIN (
SELECT userID, MAX(addedDate) as addedDate
FROM status
GROUP BY userID
) AS mostRecent
ORDER BY addedDate DESC
LIMIT 10
Note that if a user has multiple status updates with the same addedDate, the server will return all of them (whereas Robin's query would return an indeterminate one); if you need control over such a situation, you will need to define how one determines which such status update should be selected.
SELECT userID, max(addedDate)
FROM status
WHERE userID != "83" #This is just so my statuses don't show
GROUP BY userID
SELECT *
FROM ( SELECT *
FROM status
WHERE userID != "83"
ORDER BY addedDate DESC) AS h
GROUP BY userID
ORDER BY addedDate DESC
LIMIT 10
You must ORDER BY before GROUP BY'ing.
Example 1
Example 2
Related
I have been working in mySQL and I have been having issues with the COUNT function. I have already tried removing the spaces and the error persists.
SELECT COUNT(payment) FROM paymentType
GROUP BY payment
ORDER BY COUNT (payment) DESC
LIMIT 1;
I am trying to find the most common payment entry in the table paymentType.
If you want the most common payment, then I think you want:
SELECT payment
FROM paymentType
GROUP BY payment
ORDER BY COUNT(*) DESC
LIMIT 1;
this will work:
SELECT Count(payment),payment FROM paymentType
GROUP BY payment
ORDER BY COUNT DESC
LIMIT 1;
Note: the column you will get after the COUNT function will be a new column… And it has to have a name – so SQL automatically names it “count” (check the latest screenshot above). When you refer to this column in your ORDER BY clause, you have to use this new name
Something like this maybe?
select *
from (
select payment, count(*) as c from paymentType group by payment
) x
order by c desc
limit 1
Don't put the space in HAVING clause between COUNT and (
Try this:
ORDER BY COUNT(payment) DESC
Count aggregate function SQL
This query works and provides me with the information I need, but it is very slow: it takes 18 seconds to agregate a database of only 4,000 records.
I'm bringing it here to see if anyone has any advice on how to improve it.
SELECT COUNT( status ) AS quantity, status
FROM log_table
WHERE time_stamp
IN (SELECT MAX( time_stamp ) FROM log_table GROUP BY userid )
GROUP BY status
Here's what it does/what it needs to do in plain text:
I have a table full of logs, each log contains a "userid", "status" (integer between 1-12) and "time_stamp" (a time stamp of when the log was created). There may be many entries for a particular userid, but with a different time stamp and status. I'm trying to get the most recent status (based on time_stamp) for each userid, then count the occurrences of each most-recent status among all the users.
My initial idea was to use a sub query with GROUP BY userid, that worked fast - but that always returned the first entry for each userid, not the most recent. If I could do GROUP BY userid using time_stamp DESC to Identify which row should be the representative for the group, that would be great. But of course ORDER BY inside of group does not work.
Any suggestions?
The first thing to try is to make this an explicit join:
SELECT COUNT(status) AS quantity, status
FROM log_table join
(select lg.userid, MAX( time_stamp ) as maxts
from log_table lg
GROUP BY userid
) lgu
on lgu.userid = lg.userid and lgu.maxts = lg.time_stamp
GROUP BY status;
Another approach is to use a different where clause. This will work best if you have an index on log_table(userid, time_stamp). This approach is doing the filtering by saying "there is no timestamp bigger than this one for a given user":
SELECT COUNT(status) AS quantity, status
FROM log_table
WHERE not exists (select 1
from log_table lg2
where lgu.userid = lg.userid and lg2.time_stamp > lg.time_stamp
)
GROUP BY status;
I have two tables:
Members:
id username
Trips:
id member_id flag_status created
("YES" or "NO")
I can do a query like this:
SELECT
Trip.id, Trip.member_id, Trip.flag_status
FROM
trips Trip
WHERE
Trip.member_id = 1711
ORDER BY
Trip.created DESC
LIMIT
3
Which CAN give results like this:
id member_id flag_status
8 1711 YES
9 1711 YES
10 1711 YES
My goal is to know if the member's last three trips all had a flag_status = "YES", if any of the three != "YES", then I don't want it to count.
I also want to be able to remove the WHERE Trip.member_id = 1711 clause, and have it run for all my members, and give me the total number of members whose last 3 trips all have flag_status = "YES"
Any ideas?
Thanks!
http://sqlfiddle.com/#!2/28b2d
In that sqlfiddle, when the correct query i'm seeking runs, I should see results such as:
COUNT(Member.id)
2
The two members that should qualify are members 1 and 3. Member 5 fails because one of his trips has flag_status = "NO"
You could use GROUP_CONCAT function, to obtain a list of all of the status ordered by id in ascending order:
SELECT
member_id,
GROUP_CONCAT(flag_status ORDER BY id DESC) as status
FROM
trips
GROUP BY
member_id
HAVING
SUBSTRING_INDEX(status, ',', 3) NOT LIKE '%NO%'
and then using SUBSTRING_INDEX you can extract only the last three status flags, and exclude those that contains a NO. Please see fiddle here. I'm assuming that all of your rows are ordered by ID, but if you have a created date you should better use:
GROUP_CONCAT(flag_status ORDER BY created DESC) as status
as Raymond suggested. Then, you could also return just the count of the rows returned using something like:
SELECT COUNT(*)
FROM (
...the query above...
) as q
Although I like the simplicity of fthiella's solution, I just can't think of a solution that depends so much on data representation. In order not to depend on it you can do something like this:
SELECT COUNT(*) FROM (
SELECT member_id FROM (
SELECT
flag_status,
#flag_index := IF(member_id = #member, #flag_index + 1, 1) flag_index,
#member := member_id member_id
FROM trips, (SELECT #member := 0, #flag_index := 1) init
ORDER BY member_id, id DESC
) x
WHERE flag_index <= 3
GROUP BY member_id
HAVING SUM(flag_status = 'NO') = 0
) x
Fiddle here. Note I've slightly modified the fiddle to remove one of the users.
The process basically ranks the trips for each of the members based on their id desc and then only keeps the last 3 of them. Then it makes sure that none of the fetched trips has a NO in the flag_status. FInally all the matching meembers are counted.
I would like to determine two things from a single query:
Most prevalent column in a table
The amount of times such column was located upon querying the table
Example Table:
user_id some_field
1 data
2 data
1 data
The above would return user_id # 1 as being the most prevalent in the table, and it would return (2) for the total amount of times that it was located in the table.
I have done my research and I came across two types of queries.
GROUP BY user_id ORDER BY COUNT(*) DESC
SUM
The problem is that I can't figure out how to use these two queries in conjunction with one another. For example, consider the following query which successfully returns the most prevalent column.
$top_user = "SELECT user_id FROM table_name GROUP BY user_id ORDER BY COUNT(*) DESC";
The above query returns "1" based on the example table shown above. Now, I would like to be able to return "2" for the total amount of times the user_id (1) was found in the table.
Is this by any chance possible?
Thanks,
Evan
You can include count(*) in the SELECT list:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC;
If you want only the first one:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC LIMIT 1;
I have made a simple auction section on my site, and I would like to display the user's current high bid on their My Bids page. I have a table that holds each unique bid that has the unique auction_id. My current query is as follows, but this only orders the groups instead of ordering what is inside the groups as well. I only want the highest value in each group.
SELECT *
FROM tblAuctionBids
WHERE username = '$username'
GROUP BY auction_id
ORDER BY id DESC
LIMIT 10
SELECT MAX(bid), *
FROM tblAuctionBids
WHERE username='$username'
GROUP BY auction_id
ORDER BY id DESC
LIMIT 10