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
Related
I already have a table, "table_one", set up on phpMyAdmin that has the following columns:
USER_ID: A discord user ID (message.author.id)
USER_NAME: A discord username (message.author.name)
USER_NICKNAME: The user's display name on the server (message.author.display_name)
TIMESTAMP: A datetime timestamp when the message was entered (message.created_at)
MESSAGE CONTENT: A cleaned input keyword to successful completion of content, just for this example consider "apple" or "orange" as the two target keywords.
What I'd like as a result is a view or query that returns a table with the following:
The user's most recent display name (USER_NICKNAME), based off the most recent timestamp
The total number of times a user has entered a specific keyword. Such as confining the search to only include "apple" but not instances "orange"
My intention is that if a user entered a keyword 10 times, then changed their server nickname and entered the same keyword 10 more times, the result would show their most recent nickname and that they entered the keyword 20 times in total.
This is the closest I have gotten to my desired result so far. The query correctly groups instances where user has changed their nickname based on the static discord ID, but I would like it to retain this functionality while instead showing the most recent USER_NICKNAME instead of a USER_ID:
SELECT USER_ID, COUNT(USER_ID)
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID
I don't think there is an uncomplicated way to do this. In Postgres, I would use the SELECT DISTINCT ON to get the nickname, but in MySQL I believe you are limited to JOINing grouped queries.
I would combine two queries (or three, depending how you look at it).
First, to get the keyword count, use your original query:
SELECT USER_ID, COUNT(USER_ID) as apple_count
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID;
Second, to get the last nickname, group by USER_ID without subsetting rows and use the result as a subquery in a JOIN statement:
SELECT a.USER_ID, a.USER_NICKNAME AS last_nickname
FROM table_one a
INNER JOIN
(SELECT USER_ID, MAX(TIMESTAMP) AS max_ts
FROM table_one
GROUP BY USER_ID) b
ON a.USER_ID = b.USER_ID AND TIMESTAMP = max_ts
I would then JOIN these two, using a WITH statement to increase the clarity of what's going on:
WITH
nicknames AS
(SELECT a.USER_ID, a.USER_NICKNAME AS last_nickname
FROM table_one a
INNER JOIN
(SELECT USER_ID, MAX(TIMESTAMP) AS max_ts
FROM table_one
GROUP BY USER_ID) b
ON a.USER_ID = b.USER_ID AND TIMESTAMP = max_ts),
counts AS
(SELECT USER_ID, COUNT(USER_ID) AS apple_count
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID)
SELECT nicknames.USER_ID, nicknames.last_nickname, counts.apple_count
FROM nicknames
INNER JOIN counts
ON nicknames.USER_ID = counts.USER_ID;
Actually, i did counted distinct empid rows according to dates. But the problem is i get only one empid record of that specific dates.Please let me know how to get all empid records. Here is my sql query.
$sql = "
SELECT COUNT(DISTINCT subcount.empid) AS CountOf
, subcount.name
, subcount.date
, subcount.empid
, calendar.cdate
FROM subcount
, calendar
WHERE subcount.date = calendar.cdate
GROUP
BY subcount.date
";
Here is sql database.
For example, When you look at 2020-11-10 there are two empid with 10 and 7.
When i tried to get both records i get only empid 10 record or 7 record, though i need both record counts:
Here is the output:
Please help me on this.
I think what you are asking is to get list of employees with count of their submissions on a given date, this could show do it:
SELECT cnt.empid AS EmpId
, sc.Name
, cnt.`date` AS Timestamp
, cnt.CountOf AS SubmissionCount
FROM subcount AS sc
INNER JOIN
(
SELECT subcount.empid
subcount.`date`,
count(*) AS CountOf
FROM subcount
INNER JOIN calendar
ON subcount.`date` = calendar.cdate
GROUP BY
subcount.`date`, subcount.empid
) AS cnt
ON sc.empid == cnt.empid
It uses nested SELECT with GROUP BY to calculate count per employee (empid) and date (not only employee). Outer SELECT join nested SELECT to get subcount.Name piece of data which isn't retrieved in nested SELECT so it needs to be retrieved using outer SELECT.
GROUP BY ___ means result rows per ___. If you group by employee ID, you get one row per employee ID. If you want one row per employee ID and date, group by employee ID and date.
SELECT any_value(s.name), s.`date`, s.empid, c.cdate, count(*)
FROM subcount s
JOIN calendar c on c.cdate = s.`date`
GROUP BY s.`date`, s.empid
ORDER BY s.`date`, s.empid;
I expect a calendar table to have one row per date, so there is exactly one cdate for a result row. The name, however, can be different from row to row, so we must tell the DBMS, which to pick. With ANY_VALUE I tell it that I don't care which.
enter image description hereI have an employee table. In that table I have n number of loan.. Now I want to select all the employees with his last taken loan value and date.. can anyone help me out in this.
There's what I've done so far:
SELECT employee_id,employee_name,department_name,
designation_name,PF_type,PF_number,Opening_balance,
MAX(Loan_id),MAX(loan_date), MAX(loan_amount)
FROM single_roww1
GROUP BY employee_id
I tried group by, limit and order by for this but of no use... I also tried to take the last occurence of the employee_id that also didn't work..
Update: to get the full row of max id:
SELECT *
FROM loan
INNER JOIN
(SELECT max(id) max_id
FROM loan
GROUP BY employee_id) x ON x.max_id = loan.id
group by employee_id;
I have to mention that your DB table design without primary key isn't well designed: https://i.stack.imgur.com/DTYO8.png
If only the row containing the last loan_id is required than a correlated sub query is what you want
SELECT *
FROM single_roww1 SR
WHERE LOAN_ID = (SELECT MAX(LOAN_ID) FROM single_roww1 WHERE EMPLOYEE_ID = SR.EMPLOYEE_ID);
With a correlated subquery in the WHERE clause:
SELECT s.employee_id, s.employee_name, s.department_name,
s.designation_name, s.PF_type, s.PF_number, s.Opening_balance,
s.Loan_id, s.loan_date, s.loan_amount
FROM single_roww1 s
WHERE s.Loan_id = (SELECT MAX(Loan_id) FROM single_roww1 WHERE employee_id = s.employee_id)
last taken loan value and date
You seem to want:
SELECT sr.*
FROM single_roww1 sr
WHERE sr.loan_date = (SELECT MAX(sr2.load_date)
FROM single_roww1 sr2
WHERE sr2.employee_id = sr.employee_id
);
This assumes shat loan_date has a proper date/time type in the database (despite what the data in the image looks like).
For performance, you want an index on (employee_id, load_date).
Note that if an employee has multiple loans on the same date, this will retrieve the last one.
SELECT *
FROM table
INNER JOIN
(SELECT itemno, MAX(last_updated) as TopDate
FROM table
WHERE userID = 'user'
GROUP BY itemno) AS EachItem ON
EachItem.TopDate = table.last_updated
AND EachItem.itemno = table.itemno
I have taken the solution above from a previous post and modified it to work with one of the functions that I have created but I now want to use this same query but adapt it to order the result by max(last_updated) (which is a timestamp in my table) and also max(qty_sold).
Basically I have multiple duplicates of itemnos in the table but only want to return the rows with the latest date and highest qty_sold for every row where a certain user ID is specified.
Many thanks in advance, I have spent hours searching and can't figure this out as I am fairly new to mysql.
Solved my own question after more trying by adding ORDER BY qty_sold DESC to the end.
SELECT *
FROM table
INNER JOIN
(SELECT itemno, MAX(last_updated) as TopDate
FROM table
WHERE userID = 'user'
GROUP BY itemno) AS EachItem ON
EachItem.TopDate = table.last_updated
AND EachItem.itemno = table.itemno
ORDER BY qty_sold DESC
I have 2 tables: users_item that has 2 columns user_id, item_id and item_rates that has 2 columns rate_item_id, rate.
They are connected with Foreign_Key on users_item.item_id = item_rates.rate_item_id. I need to
select item_id's with max rate for a given range of users. One user can have a lot of items.
My select is:
SELECT MAX(rate), rate_item_id, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
AND user_id in (2706,2979) GROUP BY user_id;
but it returns not correspondent item_id's with max rate. In given example select has to return just 2 rows. Can someone help on this. Thanks in advance.
Ok, I found what you want.. Try this:
SELECT users_item.user_id, item_id, maxrate
FROM user_items
JOIN item_rates ON users_item.item_id = item_rates.rate_item_id
JOIN (SELECT MAX(rate) AS maxrate, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
WHERE user_id in (1,2)
GROUP BY user_id) AS maxis
ON users_item.USER_ID = maxis.USER_ID
WHERE item_rates.rate = maxrate
The reason you need a subquery is that multiple different items own by the same user could have the same rate and this could be the maximum rate of user's owned items.
Try grouping by user_id, rate_item_id
I'm surprised that MySql doesn't give you an error, Oracle would...