Getting Newest Record from a table using mysql - mysql

This has to be a no brainer, but I am stumped. I'm used to using aggregate 'FIRST' in MsAccess, but MySql has no such thing.
Here is a simple table. I want to return the most recent record based on the date,
for each unique 'group ID'. I need the three records in yellow.
I was asked to add my full query. I tried one of the suggestions using the JOIN feature replacing 't' with the temp table name, but it failed to work. "Can't reopen table 't'"
The code is below. I know it's ugly, but it does return the correct data set.
I cleaned up the code a bit and added the JOIN code. Error: "Can't reopen table 't'"
enter code here
DROP TABLE IF EXISTS `tmpMaxLookupResults`;
create temporary table tmpMaxLookupResults
as
SELECT
REPORTS.dtmReportCompleted,
RESULTS.lngMainReport_ID, RESULTS.lngLocationGroupSub_ID
FROM
(tbl_010_040_ProcedureVsTest_Sub as ProcVsSub
INNER JOIN tbl_010_050_CheckLog_RESULTS as RESULTS
ON (ProcVsSub.lngLocationGroupSub_ID = RESULTS.lngLocationGroupSub_ID)
AND (ProcVsSub.lngProcedure_ID = RESULTS.lngProcedure_ID)
AND (ProcVsSub.lngItemizedTestList_ID = RESULTS.lngItemizedTestList_ID)
AND (ProcVsSub.strPasscodeAdmin = RESULTS.strPasscodeAdmin)
AND (ProcVsSub.strCFICode = RESULTS.strCFICode))
INNER JOIN
tbl_000_010_MAIN_REPORT_INFO as REPORTS ON (RESULTS.lngPCC_ID =
REPORTS.lngPCC_ID)
AND (RESULTS.lngProcedure_ID = REPORTS.lngProcedure_ID)
AND (RESULTS.lngMainReport_ID = REPORTS.idMainReport_ID)
AND (RESULTS.strPasscodeAdmin = REPORTS.strPasscodeAdmin)
AND (RESULTS.strCFICode = REPORTS.strCFICode)
WHERE
(((RESULTS.lngProcedure_ID) = 143)
AND ((RESULTS.dtmExpireDate) IS NOT NULL)
AND ((RESULTS.strCFICode) = 'ems'))
GROUP BY RESULTS.lngMainReport_ID, RESULTS.lngLocationGroupSub_ID
ORDER BY (REPORTS.dtmReportCompleted) DESC;
SELECT t.*
FROM tmpMaxLookupResults AS t
JOIN (
SELECT lngLocationGroupSub_ID,
MAX(dtmReportCompleted) AS max_date_completed
FROM tmpMaxLookupResults
GROUP BY lngLocationGroupSub_ID ) AS dt
ON dt.lngLocationGroupSub_ID = t.lngLocationGroupSub_ID AND
dt.max_date_completed = t.dtmReportCompleted
enter code here

Try this
SELECT
tn.*
FROM
tableName tn
RIGHT OUTER JOIN
(
SELECT
groupId, MAX(date_completed) as max_date_completed
FROM
tableName
GROUP BY
groupId
) AS gt
ON
(gt.max_date_completed = nt.date_completed AND gt.groupId = nt.groupId)

You can use the following SQL.
select * from table1 order by date_completed desc Limit 1;

Use Order By
SELECT *
FROM table_name
ORDER BY your_date_column_name
DESC
LIMIT 1

In a Derived Table, get the maximum date_completed value for every group_id.
Join this result-set back to the main table, in order to get the complete row corresponding to maximum date_completed value for every group_id
Try the following query:
SELECT t.*
FROM your_table_name AS t
JOIN (
SELECT group_id,
MAX(date_completed) AS max_date_completed
FROM your_table_name
GROUP BY group_id
) AS dt
ON dt.group_id = t.group_id AND
dt.max_date_completed = t.date_completed

Related

MySQL, joining a table where you require the max value from the second table

I have the below query:
SELECT users_service.id, name
FROM users_service
LEFT JOIN
(SELECT * FROM activity)
activity ON (users_service.id = activity.user_service_id)
WHERE admin_id = 1
However, this returns as many results from the activity table as exist, ie multiple activity results for each admin_id entry.
I desire to return only the latest row from the activity table for each admin_id.
This could be entry_date or id.
I tried using distinct & max and limit 1, but these all produced strange behavior.
Use ROW_NUMBER():
SELECT us.id, a.name
FROM users_service us LEFT JOIN
(SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY a.user_service id ORDER BY ? DESC) as seqnum
FROM activity
) a
ON u.id = a.user_service_id AND seqnum = 1
WHERE u.admin_id = 1;
The ? is for the column that specifies the "most recent", which your question doesn't clarify.
You did not specify the column by which you determine the most recent activity. I call it datetime_col in the solution below:
SELECT users_service.id
, name
FROM users_service usv
LEFT
JOIN activity act
on act.users_service.id = usv.user_service_id
and act.datetime_col = (select max(datetime_col)
from activity act_
WHERE act_.user_service_id= act.user_service_id)

order by and group by both at time not working

My query is below
SELECT *
FROM
(
SELECT
usr.*,
messages.message_text, messages.message_id
FROM
`user` as usr
LEFT JOIN
(
SELECT
message.*
FROM
message AS message
ORDER BY
message.updated_at
DESC
) AS messages
ON
`usr`.`user_id` = `messages`.`sender_id` OR `usr`.`user_id` = `messages`.`receiver_id`
WHERE
`usr`.`is_delete` = 0 AND `usr`.`is_active` = 1
ORDER BY
messages.updated_at
DESC
) AS result
GROUP BY
result.user_id
if i remove the group by then it work well , but i want the result with group by Please Help.
I have one message table in that i have saved the sender id and receiver id, both id have foreign key with user table and i want the recent message send by user and user details
So for latest message i am using order by desc and after getting all the messages with descending order i am using group by but it is not working.
It was very hard making the table schemas and the data insert in them which would act like your scenario. So next time, please provide a fiddle link to your schema/situation.
Here were the issues in your query:
You dont need a subquery after LEFT JOIN
ORDER BY clause is always after GROUP BY
You must mention all the columns that you are SELECTing in the GROUP BY clause.
Tweaked your query a bit:
SELECT *
FROM
(
SELECT
usr.*,
messages.message_text, messages.message_id, messages.updated_at
FROM
user as usr
LEFT JOIN message messages
--(
-- SELECT
-- message.*
-- FROM
-- message AS message
-- ORDER BY
-- message.updated_at
-- DESC
--) AS messages
ON
usr.user_id = messages.sender_id OR usr.user_id = messages.receiver_id
WHERE
usr.is_delete = 0 AND usr.is_active = 1
--ORDER BY
--messages.updated_at
--DESC
) AS result
GROUP BY
result.user_id,result.name,result.is_delete,result.is_active,result.message_text,result.message_id,updated_at
ORDER BY
result.updated_at
DESC
Hope it helps :)

LEFT JOIN SUM with WHERE clause

The following query always outputs SUM for all rows instead of per userid. Not sure where else to look. Please help.
SELECT * FROM assignments
LEFT JOIN (
SELECT SUM(timeworked) AS totaltimeworked
FROM time_entries
) assignments ON (userid = assignments.userid AND ticketid = ?)
WHERE ticketid = ?
ORDER BY assigned,scheduled
If you want to keep the SELECT *, you would have to add a group by clause in the subquery. Something like this
SELECT * FROM assignments
LEFT JOIN (
SELECT SUM(timeworked) AS totaltimeworked
FROM time_entries
GROUP BY userid
) time_entriesSummed ON time_entriesSummed.userid = assignments.userid
WHERE ticketid = ?
ORDER BY assigned,scheduled
But a better way would be to change the SELECT * to instead select the fields you want a add a group by clause directly. Something like this
SELECT
assignments.id,
assignments.assigned,
assignments.scheduled,
SUM(time_entries.timeworked) AS totalTimeworked
FROM assignments
LEFT JOIN time_entries
ON time_entries.userid = assignments.userid
GROUP BY assignments.id, assignments.assigned, assignments.scheduled
Edit 1
Included table names in query 2 as mentioned in chameera's comment below

MySQL Inner Join with where clause sorting and limit, subquery?

Everything in the following query results in one line for each invBlueprintTypes row with the correct information. But I'm trying to add something to it. See below the codeblock.
Select
blueprintType.typeID,
blueprintType.typeName Blueprint,
productType.typeID,
productType.typeName Item,
productType.portionSize,
blueprintType.basePrice * 0.9 As bpoPrice,
productGroup.groupName ItemGroup,
productCategory.categoryName ItemCategory,
blueprints.productionTime,
blueprints.techLevel,
blueprints.researchProductivityTime,
blueprints.researchMaterialTime,
blueprints.researchCopyTime,
blueprints.researchTechTime,
blueprints.productivityModifier,
blueprints.materialModifier,
blueprints.wasteFactor,
blueprints.maxProductionLimit,
blueprints.blueprintTypeID
From
invBlueprintTypes As blueprints
Inner Join invTypes As blueprintType On blueprints.blueprintTypeID = blueprintType.typeID
Inner Join invTypes As productType On blueprints.productTypeID = productType.typeID
Inner Join invGroups As productGroup On productType.groupID = productGroup.groupID
Inner Join invCategories As productCategory On productGroup.categoryID = productCategory.categoryID
Where
blueprints.techLevel = 1 And
blueprintType.published = 1 And
productType.marketGroupID Is Not Null And
blueprintType.basePrice > 0
So what I need to get in here is the following table with the columns below it so I can use the values timestamp and sort the entire result by profitHour
tablename: invBlueprintTypesPrices
columns: blueprintTypeID, timestamp, profitHour
I need this information with the following select in mind. Using a select to show my intention of the JOIN/in-query select or whatever that can do this.
SELECT * FROM invBlueprintTypesPrices
WHERE blueprintTypeID = blueprintType.typeID
ORDER BY timestamp DESC LIMIT 1
And I need the main row from table invBlueprintTypes to still show even if there is no result from the invBlueprintTypesPrices. The LIMIT 1 is because I want the newest row possible, but deleting the older data is not a option since history is needed.
If I've understood correctly I think I need a subquery select, but how to do that? I've tired adding the exact query that is above with a AS blueprintPrices after the query's closing ), but did not work with a error with the
WHERE blueprintTypeID = blueprintType.typeID
part being the focus of the error. I have no idea why. Anyone who can solve this?
You'll need to use a LEFT JOIN to check for NULL values in invBlueprintTypesPrices. To mimic the LIMIT 1 per TypeId, you can use the MAX() or to truly make sure you only return a single record, use a row number -- this depends on whether you can have multiple max time stamps for each type id. Assuming not, then this should be close:
Select
...
From
invBlueprintTypes As blueprints
Inner Join invTypes As blueprintType On blueprints.blueprintTypeID = blueprintType.typeID
Inner Join invTypes As productType On blueprints.productTypeID = productType.typeID
Inner Join invGroups As productGroup On productType.groupID = productGroup.groupID
Inner Join invCategories As productCategory On productGroup.categoryID = productCategory.categoryID
Left Join (
SELECT MAX(TimeStamp) MaxTime, TypeId
FROM invBlueprintTypesPrices
GROUP BY TypeId
) blueprintTypePrice On blueprints.blueprintTypeID = blueprintTypePrice.typeID
Left Join invBlueprintTypesPrices blueprintTypePrices On
blueprintTypePrice.TypeId = blueprintTypePrices.TypeId AND
blueprintTypePrice.MaxTime = blueprintTypePrices.TimeStamp
Where
blueprints.techLevel = 1 And
blueprintType.published = 1 And
productType.marketGroupID Is Not Null And
blueprintType.basePrice > 0
Order By
blueprintTypePrices.profitHour
Assuming you might have the same max time stamp with 2 different records, replace the 2 left joins above with something similar to this getting the row number:
Left Join (
SELECT #rn:=IF(#prevTypeId=TypeId,#rn+1,1) rn,
TimeStamp,
TypeId,
profitHour,
#prevTypeId:=TypeId
FROM (SELECT *
FROM invBlueprintTypesPrices
ORDER BY TypeId, TimeStamp DESC) t
JOIN (SELECT #rn:=0) t2
) blueprintTypePrices On blueprints.blueprintTypeID = blueprintTypePrices.typeID AND blueprintTypePrices.rn=1
You don't say where you are putting the subquery. If in the select clause, then you have a problem because you are returning more than one value.
You can't put this into the from clause directly, because you have a correlated subquery (not allowed).
Instead, you can put it in like this:
from . . .
(select *
from invBLueprintTypesPrices ibptp
where ibtp.timestamp = (select ibptp2.timestamp
from invBLueprintTypesPrices ibptp2
where ibptp.blueprintTypeId = ibptp2.blueprintTypeId
order by timestamp desc
limit 1
)
) ibptp
on ibptp.blueprintTypeId = blueprintType.TypeID
This identifies the most recent records for all the blueprintTypeids in the subquery. It then joins in the one that matches.

MySQL views cannot have subquery in from, and don't maintain order. How can I create a view from this query?

I'm essentially trying to obtain a resultset with each employee's current title. I'd like to create a view from this for later use, but I find I'm being stumped, and likely missing a simple solution. Here's the query in question, and thanks in advance!
select * from
(SELECT
appointment.employee_id,
title.`name` as title_name
FROM
appointment
INNER JOIN appointment_title ON appointment.id = appointment_title.appointment_id
INNER JOIN title ON appointment_title.title_id = title.id
order by appointment_title.effective_date DESC) tmp group by employee_id
Updated:
SELECT
appointment.employee_id ,
( SELECT title.`name`
FROM appointment_title
INNER JOIN title
ON appointment_title.title_id = title.id
WHERE appointment.id = appointment_title.appointment_id
ORDER BY appointment_title.effective_date DESC
LIMIT 1
) AS title_name
FROM appointment
GROUP BY appointment.employee_id
Another option is to break up the query into two views. The first view will contain the derived table subquery, and the second will simply select from that one:
CREATE VIEW vwEmployee_Inner AS
SELECT
appointment.employee_id,
title.`name` as title_name
FROM
appointment
INNER JOIN appointment_title ON appointment.id = appointment_title.appointment_id
INNER JOIN title ON appointment_title.title_id = title.id
order by appointment_title.effective_date DESC
And then your original view becomes:
CREATE VIEW vwEmployee AS
SELECT * FROM vwEmployee_Inner GROUP BY employee_id