Say I have a table that stores each and every time someone does something (let's say jumps)
The table has a JumpNumber (auto-increments each time there's an insert, so there's one for every jump rather than this being a total). It also records the member who jumped as MemberID, and the time they jumped at.
I would like to make a query that finds the most occurring member then gives their ID and every time at which they've ever jumped.
However, if there's 2 or more members with the most jumps (so a tie) it should still display each of them, with their jump times.
So I couldn't just do a descending order and limit to 1. I'm also confused as to how I should find the most reoccurring member, I'm guessing a COUNT but not 100% sure how.
Well it would be something like:
SELECT USER_ID
FROM YOURTABLE A
WHERE JUMPS = (SELECT MAX(JUMPS)
FROM YOURTABLE B)
This will return all USER_ID with the most Jumps, then you can select all records where the selectes user(s) made something
If you store jumps, use variant by Xavjer
If you not store jumps, first you have find max count
select user_id, count(*) as c from TABLE group by user_id order by c desc limit 1
After that you have do same grouping again and select all user_id with that count and left join original table for other fields.
select A.* from (
select user_id from
(select user_id, count(*) as c from TABLE group by user_id) as tempB
) as tempC where tempC.c=(
select count(*) as c from TABLE group by user_id order by c desc limit 1
)
) as join_table1
LEFT JOIN TABLE as A on A.user_id=join_table1;
Related
Here is my situation:
I have 4 tables that all contains a column called score in all of these tables my goal for a view to create operations to the result of the 4 tables getting the following values:
Total score
Total number of rows
average (total score / number of rows)
Now i know that i would be able to create the view as:
(SELECT * FROM table1 where condition) + (SELECT * FROM table2 where condition)
So on and so forth.
but for each of the three goals i have i would have to nested select all tables atleast 2 times.
So my question is how do you handle a case like this? is there any operation in sql that makes this an easy task or am i bound to do something redundant?
Update
So my full case is that every use in my system has something called a division_id now i want to use this ID to find out what the score is for each division:
(PLEASE IGNORE THE _COPY)
You could use a UNION to join the 4 tables, since there is no join condition. There are a couple of ways that you could do this with the division field. Probably the most concise is:
select division_id, count(*), avg(scores.score), sum(scores.score) from
user join
(select id as user_id, score from user
UNION ALL
select user_id, score from test_score
UNION ALL
select user_id, score from task_score
UNION ALL
select user_id, score from offline_score) as scores
on user.id = scores.user_id
group by division_id
Link to SQLFiddle
I have a MySQL table where I have a certain id as a foreign key coming from another table. This id is not unique to this table so I can have many records holding the same id.
I need to find out which ids are seen the least amount of times in this table and pull up a list containing them.
For example, if I have 5 records with id=1, 3 records with id=2 and 3 records with id=3, I want to pull up only ids 2 & 3. However, the data in the table changes quite often so I don't know what that minimum value is going to be at any given moment. The task is quite trivial if I use two queries but I'm trying to do it with just one. Here's what I have:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = MIN(SELECT COUNT(*) FROM table GROUP BY id)
If I substitute COUNT(*) = 3, then the results come up but using the query above gives me an error that MIN is not used properly. Any tips?
I would try with:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM table GROUP BY id ORDER BY COUNT(*) LIMIT 1);
This gets the minimum selecting the first row from the set of counts in ascendent order.
You need a double select in the having clause:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT MIN(cnt) FROM (SELECT COUNT(*) as cnt FROM table GROUP BY id) t);
The MIN() aggregate function is suposed to take a column, not a query. So, I see two ways to solve this:
To properly write the subquery, or
To use temp variables
First alternative:
select id
from yourTable
group by id
having count(id) = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
)
Second alternative:
set #minCount = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
);
select id
from yourTable
group by id
having count(*) = #minCount;
You need to GROUP BY to produce a set of grouped values and additional select to get the MIN value from that group, only then you can match it against having
SELECT * FROM table GROUP BY id
HAVING COUNT(*) =
(SELECT MIN(X.CNT) AS M FROM(SELECT COUNT(*) CNT FROM table GROUP BY id) AS X)
I have a history table, and I need to retrieve the last known status for each asset ID. Here's my current query:
SELECT a.AutoID AS AssetID,
(SELECT LastFound FROM Device_Status_History b WHERE a.AutoID = b.AssetID ORDER BY AutoID DESC LIMIT 0,1) LastFound,
(SELECT CheckDate FROM Device_Status_History c WHERE a.AutoID = c.AssetID ORDER BY AutoID DESC LIMIT 0,1) CheckDate
FROM (SELECT AutoID FROM Devices UNION SELECT AutoID FROM Switches) a
The union subquery gets all of the asset IDs that I care to know about, and then I use the other two subqueries to get the LastFound and CheckDate columns from the history table. Overall, this works pretty good, but I would like to be able to combine the two history subqueries if possible, maybe even make it a join somehow, but I don't know how I can join while still using limit. We're running this on a Raspberry Pi, so it's desirable to squeeze every ounce of performance we can out of this.
Don't know if it's faster... But do give it a try:
SELECT AssetID, LastFound, CheckDate
FROM Device_Status_History
WHERE AssetID IN (SELECT AutoID FROM Devices UNION SELECT AutoID FROM Switches)
AND AutoID IN (SELECT MAX(AutoID) FROM Device_Status_History GROUP BY AssetID);
Also note that if you have no other AssetID's in your Device_Status_History table aside from the ones in the Devices and Switches tables, you can leave out the third line, so that the query becomes:
SELECT AssetID, LastFound, CheckDate
FROM Device_Status_History
WHERE AutoID IN (SELECT MAX(AutoID) FROM Device_Status_History GROUP BY AssetID);
I have collected informations from different sources about certain IDs that should match a single name. Some sources are more trustworthy than others in giving the correct name for a given ID.
I created a table (name, id, source_trustworthiness) and I want to get the most trustworthy name for each ID.
I tried
SELECT name, id, MAX( source_trustworthiness )
FROM table
GROUP BY id
this returns th highest trustworthiness available for each ID but with the first name it finds, regarless of its trustworthiness.
Is there a way I can get that right ?
Mysql has special functionality to help:
SELECT * FROM (
SELECT name, id, source_trustworthiness
FROM table
ORDER BY 3 DESC ) x
GROUP BY id
Although this wouldn't even execute in other databases (not naming all non-aggregate columns in the GROUP BY clause), with mysql it returns the first row encountered for each unique value of the grouped by columns. By ordering the rows greatest first, the first row for each id will be the most trustworthy.
Since this question is tagged mysql, this query is OK. Not only is it really simple, it's also quite fast.
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT id, MAX(source_trustworthiness) max_val
FROM TableName
GROUP BY ID
) b ON a.ID = b.ID AND
a.source_trustworthiness = b.max_val
I need help returning a relevant result for this query. I have one table that I am hitting with three columns. trans_date, trans_amount and user_id
what I am trying to determine is this. For a given user_id when was the last trans_date and what was the trans_amount.
I'm having trouble returning the correct transaction_amount. Here is my code so far. It's returning the correct date but the amount is not right
select user_id, trans_date, trans_credit
from table
WHERE trans_credit =
(select max(trans_date) from inclick_account_act as f
where f.user_id = table.user_id);
Thanks in advance
If I understand you correctly you just want to get the most recent transaction for all users.
SELECT user_id, trans_date, trans_credit
FROM `table`
GROUP BY user_id
ORDER BY trans_date DESC;
How about something like
SELECT t.*
FROM table t INNER JOIN
(
SELECT user_id,
MAX(trans_date) max_trans_date
FROM table
GROUP BY user_id
) MaxDates ON t.user_id = MaxDates.max_trans_date