Mysql Query to Group and Limit 1 Desc - mysql

Table name : users
I am trying to query this table such that it gives me a result showing - names for users - where - the last approved status - group by name - has manager_2 as Stan
Expected result image below
Something like
SELECT id,name,manager_1,manager_2,department_status_fruits
FROM users
WHERE status = --- the last approved entry for (group by Name),
if manager_2 = stan
ORDER BY id DESC
LIMIT 1
SELECT id,name,manager_1,manager_2,department_status_fruits
FROM users
WHERE manager_2 = 'stan' AND status = 'approved'
group by name
ORDER BY id DESC
LIMIT 1
None of the queries I tried are giving the expected results, infact I am finding it hard to even form a query to explain the request.
I guess, sub queries or joins is what i will have to go for, please suggest, joins is what I would prefer though.

You need to use a query that returns the last approved row for each name. See SQL select only rows with max value on a column for various ways to do this.
Then you can further filter this to those where manager_2 = 'stan'.
SELECT u1.*
FROM users AS u1
JOIN (SELECT name, MAX(id) AS maxid
FROM users
WHERE status = 'approved'
GROUP BY name) AS u2 ON u1.id = u2.id
WHERE manager_2 = 'stan'
ORDER BY id DESC
LIMIT 1

Related

Using JOIN in sql for two derived tables

Basically, I have two separate queries, which I need to somehow merge into one set of results.
![This is Table 1, which shows the sum of each group's salary]
1
Here is the queries I wrote to form the tables.
SELECT con_stagename, SUM(p_daily_salary) AS sum_salary
FROM CONTENDER, PARTICIPANT
WHERE p_contender = con_id
GROUP BY con_id;
SELECT MAX(sum_salary) AS max_salary
FROM (SELECT con_stagename, SUM(p_daily_salary) AS sum_salary
FROM CONTENDER, PARTICIPANT
WHERE p_contender = con_id
GROUP BY con_id) T2;
And the question is, if I want the result to be a single row of values, which the name of the group with the highest salary, and the actual amount. How would I do it? I've been trying to use JOIN operations but there was not luck.
SELECT con_stagename, SUM(p_daily_salary) AS sum_salary
FROM CONTENDER, PARTICIPANT
WHERE p_contender = con_id
GROUP BY con_id
ORDER BY 2 DESC
LIMIT 1

MYSQL using other tables

This query:
SELECT
user_id,
count(base_item)
FROM items
WHERE base_item = '202'
group by user_id order by count(base_item)
Gives me this result:
which I want.
However, I also want it to exclude all user ids in the users table with a rank of 5 or greater. as shown here
Modify your where clause this way:
WHERE base_item = '202' AND user_id NOT IN (SELECT id FROM users WHERE rank > 5)
The portion in parentheses is called a subquery. The result set of the subquery contains the id of all users with a rank greater than 5. The addition to the where clause excludes all users in that result set.
Join with the users table and filter out rows with high rank
SELECT user_id, count(*) AS count
FROM items AS i
JOIN users AS u ON i.user_id = u.id
WHERE i.base_item = '202'
AND u.rank <= 5
group by user_id
order by count

getting values from select with case/if statement depending on condition

I am stuck last 2 hours trying to figure out how to make this query or to find an example, till now no result in searching, so I will post here what is my problem. I have a group of users and there is a specific order in which I need to get values.
So group 1 is administrator and he can see all groups, for him the query to get values would be
SELECT g1.group_id,g1.description FROM groups g1 ORDER BY g1.description
Other groups can see all groups except Administrator group (id in this case is 1), for other users the query to get the values would be:
SELECT g2.group_id,g2.description FROM groups g2 WHERE g2.group_id > 1 ORDER BY g2.description
I tried to make something with CASE statement but this is not working and I know that subquery cant return more than 1 row, i get an error like this
[Err] 1242 - Subquery returns more than 1 row
My query is till now, the wrong one:
SELECT
CASE WHEN (SELECT ug.group_id FROM users_groups ug
WHERE ug.login="admin" and ug.group_id = 1)
THEN (SELECT g1.group_id,g1.description FROM groups g1 ORDER BY g1.description)
ELSE (SELECT g2.group_id,g2.description FROM groups g2 WHERE g2.group_id > 1 ORDER BY g2.description)
END
So I need results depending on the group of logged user, if user is admin and his group=1 than he can see all groups, in other way all groups except group 1, admin
any help would be appreciated, the most important thing is that I get the values in this order and only these two g1.group_id,g1.description or g2.group_id,g2.description
Desired output would be :
For user Administrator-
group_id description
1 Administrator
2 Customer
3 Supplier
For users that are not Administrator-
group_id description
2 Customer
3 Supplier
SELECT g.group_id, g.description
FROM groups AS g
CROSS JOIN user_groups AS ug
WHERE ug.login = #username
AND (ug.group_id = 1 OR g.group_id > 1)
ORDER BY g.description
#username is a placeholder for the username performing the query.

Select left join, group by user name and get the last last row

I've tried to get last entry with this query but I just can't get last row (only the first):
select users.*,messages.*
from messages
LEFT JOIN users
ON messages.messageBy=users.email
where messageToUser='{loginUser}'
GROUP BY messageBy
If you want to get last record with group by then try the below query
select users.*,message.*
from
message
LEFT JOIN
users
ON
message.messageBy = users.email
where
messageToUser=1
AND
messageid IN (SELECT max(messageid) FROM message GROUP BY messageBy)
GROUP BY
messageBy
ORDER BY
messageid DESC
rough demo at http://sqlfiddle.com/#!2/cda6f/1
So, if you have any kind of id field or date stored in your message table, you could do:
SELECT
...
ORDER BY your_date_field DESC
LIMIT 1
OR
SELECT
...
ORDER BY id DESC
LIMIT 1
Otherwise you are left with using code to count the number of records returned and just get the last one.
Oh, you want the last message from each user.
A stock solution looks like this...
SELECT x.*
FROM my_table x
JOIN (SELECT my_grouping_id,MAX(my_ordering_id) max_my_ordering_id FROM my_table GROUP BY my_grouping_id) y
ON y.my_grouping_id = x.my_grouping_id
AND y.max_my_ordering_id = x.my_ordering_id;

Retrieving most recent records in groups

What I'm looking to do is this...
I have a database that logs changes in the status of a record...
For example, it may be set as "inactive" then, a later row might reactivate the record...
1 Company1 Active
2 Company2 Active
3 Company1 Inactive
4 Company1 Active
The query needs to look for currently active results... and should return two records... (one for Company1 and one for Company2.)
I need to return only records that are CURRENTLY active.
This query does part of it...
SELECT id, gid, status
FROM companies
GROUP BY gid
HAVING status = 'Active'
ORDER BY id
But it doesn't look for results to return based on the last record...
What I am basically looking at is how to incorporate something that would check only the the most recent record like "LIMIT 1,1" with "ORDER BY id DESC) within each group... I have no idea how to incorporate it into the query.
Update I've got it down to this so far... Based on an answer but it's bringing back the last row of each group whether it is currently active or not...
select t.*
from (
select status, max(id) as id
from companies
group by gid
having status = 'Active'
) active_companies
inner join companies t on active_companies.id = t.id
If your IDs are always in ascending order, this will select the most recent ID for every company:
SELECT MAX(id), gid
FROM companies
GROUP BY gid
and this will return all the records that you need:
SELECT companies.*
FROM companies INNER JOIN (SELECT MAX(id) m_id
FROM companies
GROUP BY gid) m
ON companies.id = m.m_id
WHERE
status = 'Active'
You might also be tempted to use this little trick:
SELECT *
FROM (SELECT * FROM companies ORDER BY id DESC) t
GROUP BY gid
HAVING status='Active';
but please don't! It usually/most always work, it looks cleaner and is often faster, but relies on an undocumented behaviour, so it is not guaranteed that you will always get the correct result.
Please see fiddle here!
The following query returns the current status for each company, using a MySQL trick:
select gid, substring_index(group_concat(status order by id desc), ',', 1) as status
from companies
group by gid;
If you want only the ones that are currently active:
select gid
from companies
group by gid
having 'active' = substring_index(group_concat(status order by id desc), ',', 1)
Let's split the problem into two smaller ones:
First, you want to get the most recent entry from each group:
select max(id)
from companies
group by gid;
Next, you want to have only entries (which are last entries) and which are active:
select t.*
from companies t
inner join (
select max(id) as id
from companies
group by gid
) last_entries
on t.id = last_entries.id
where t.status = 'Active';
Try a subselect get records where status = 'Active' and order by id (which i assume is auto-increment ) desc then in parent select do group by
SELECT t.* FROM (
SELECT *
FROM companies
WHERE `status` = 'Active'
ORDER BY id DESC
) t
GROUP BY t.gid