Best Way to form this query - mysql

Team,
I have three tables.
myTransTable,myMasterTable 1, MymyMasterTable 2
myTransTable have a lot of entries 'Rank.No ' auto incerement field is to identify indvidual records . 'U.Name' holds user name. Each user can have multiple records in this table . But the most recent transaction of a user can be find by the max value for Rank.No after grouping by 'U.Name'
Once this max record i.e recent transaction is fetched their asociated data needs to fetched from other tables
How can this be done in most efficent way.
1.myTransTable(fields Rank.No(auto increment field),Name,RecNum,uname,date,type)
2.myMasterTable1 (RecNum,Recowner,recdate)
3.MymyMasterTable2 (uName,age ,address,contact num)
I tried these ways for selection the max record and fetch the assocated data from other tables
max records as a view and fetch data from other tables using normal query
Max records and associated data itself as a view and select data as needed
Which is best way to have minimum execution time?
My queries are which is the best way to find the max.
Option one
select a.`RecNum`,a.`Name`,a.`Date`, a.`type`"+
"from myTransTable a "+
"INNER JOIN "+
"(SELECT RecNumMAX(`Rank.No`) AS maxserialnum FROM myTransTable "+
"GROUP BY RecNumMAX)groupedRecNumMAX "+
" ON "+
" a.RecNum = groupedPWO.RecNum "+
"AND "+
"a.`Rank.No` = groupedRecNumMAX.maxserialnum "+
Option two
Select a.`RecNum`,a.`Name`,a.`Date`, a.`type`"+`
FROM from myTransTable a
WHERE s.`RecNum` in(select MAX(`RecNum`)
from myTransTable
group by RecNum)

This is just a suggestion adn is related to your first query .. that seems contain wrong reference to table and column name
looking to you code you should use a query like this
select a.`RecNum`
,a.`Name`
,a.`Date`
, a.`type`
from myTransTable a
INNER JOIN (
SELECT RecNum, MAX(`Rank.No`) AS maxserialnum
FROM myTransTable
GROUP BY RecNum
) g ON a.RecNum =g.RecNum AND a.`Rank.No` = g..maxserialnum
and this with proper index .. on RecNum, and Rank.No should be the most performant (you can check in explain plain and with proper execution test)
You should not use column name with dot separated name as Rank.No .. use Rank_No isteand and also for column name the is preferred lowercase not and not a mix of UpperOrLower case use underscore for separate the word instead

Related

selecting most recent row from joined table in MySQL

I have two tables, Project and Projectnote
There is a one to many relationship between project and projectnote.
I want to be able to list my projects and select the most recent projectnotes based on the id.
Is this possible to do in Mysql query, I can't figure it out.
Thanks for any help!
Edit: so far I have a basic query (below) that joins the two tables. However, this only selects projects where a note exists and I get multiple rows where there are several notes per project.
SELECT `driver_checkins`.*, `driver_trips`.`id` AS `trip_id`, `driver_trips`.`trip_num` AS `trip_num`, `driver_trips`.`status` AS `trip_status`, `driver_trips`.`ride_date` AS `ride_date`, `driver_trips`.`today_date` AS `trip_today_date`, `driver_trips`.`pick_up_time` AS `pick_up_time`, `driver_trips`.`d_time` AS `d_time`, `driver_trips`.`trip_type` AS `trip_type`
FROM `driver_checkins`
LEFT JOIN `driver_trips` ON `driver_trips`.`driver_id` = `driver_checkins`.`driver_id` WHERE `checkin_status` = 1 AND `booking_status` = 0;
Using a GROUP BY clause and the GROUP_CONCAT function should do the trick.
I am assuming that "driver_checkins" is your "Project" table and "driver_trips" is your "Projectnote" table.
SELECT `driver_checkins`.*, GROUP_CONCAT(`driver_trips`.`id`, `driver_trips`.`status` ORDER BY `driver_trips`.id DESC SEPARATOR " --- " LIMIT 3)
FROM `driver_checkins`
LEFT JOIN `driver_trips` ON `driver_trips`.`driver_id` = `driver_checkins`.`driver_id`
WHERE `checkin_status` = 1 AND `booking_status` = 0
GROUP BY `driver_checkins`.id;
This should display id and status for the last 3 driver_trips per driver_checkin, separated by " --- ".
Something to consider: while in many cases ordering by id will work chronologically, it's always better to add a timestamp column (e.g. called created) instead to order by chronologically.

DLookUp query to MySql

I am working on converting a legacy MS access system to a spring-boot application and I came across a big query. I am mostly done with converting the functions from access to mysql but not able to understand how to convert the following DLookUp sub-query as a mySql subquery
DLookUp("[price]","tbl_so","[so_id] = " & tbl_trade.so_id & " AND [product_id] = " & tbl_po.product_id
What I understood is following won't work as I don't have the Inner Joins set between the 3 tables, tbl_so, tbl_po, tbl_trade
SELECT tbl_so.price FROM tbl_so WHERE tbl_so.so_id = tbl_trade.so_id AND tbl_so.product_id = tbl_po.product_id
My question is how do I know how the tables will join with each other in this case and also when this DLookUp query is seldom used. And also the solution for this query.
Well, as a general rule, dlookup() can be replaced with a left join. However, you can also use a sub-query and they tend to be "less" change to the query.
So, if we had this:
SELECT id, partNum, dlookup("PartDescrt","tblParts","PartID = " & partNum)
as Description from tblOrders.
You would replace the above dlookup() with a sub-query like this:
SELECT id, partNum,
(select PartDescrt from tblParts where tblParts.PartID = tblOrders.PartNum)
AS Description
from tblOrders
The above is SQL or access sql syntax, but quite sure the same should work for MySQL.
If there is more then one partNumber that matches the above, then add a TOP 1, and a order by with some unique row (PK ID column is best). So the query becomes:
(select TOP 1 PartDescrt from tblParts where tblParts.PartID = tblOrders.PartNum
ORDER BY PartDescrt, ID DESC)
AS Description

SQL Query Assistance - Left join unexpected result

I have these 2 queries:
$sql = "SELECT *
FROM ultrait_wpl_properties
LEFT JOIN ultrait_wpl_property_types
ON ultrait_wpl_properties.property_type = ultrait_wpl_property_types.id
ORDER BY ultrait_wpl_properties.id ";
$sql2 = "SELECT *
FROM ultrait_wpl_properties, ultrait_wpl_property_types
WHERE ultrait_wpl_properties.property_type = ultrait_wpl_property_types.id
ORDER BY ultrait_wpl_properties.id";
For some odd reason when the IDs are output some are duplicated? By my reseaning these queries should get everything from the table in the first part and join the second table based on the WHERE condition.
<property><id>13</id></property>
<property><id>6</id></property>
<property><id>6</id></property>
<property><id>6</id></property>
<property><id>6</id></property>
<property><id>7</id></property>
This may be slightly unclear but for some reason I'm getting duplicate IDs, all i want really is to be able to access the property type which links to the ID in the second table.
I have tested both queries in phpMyAdmin and they yeild the desired result, however when I use the queries in my php script they return unexpected results.
You are getting one row for each row in table ultrait_wpl_properties. What else do you expect? If it is just one record per type, then you would have to re-write your query accordingly. You select * from both tables. But is it only the type ID you need? Then why join the tables at all?
Get all type IDs:
select id from ultrait_wpl_property_types;
Get all type IDs in table ultrait_wpl_properties:
select distinct property_type from ultrait_wpl_properties;
Get all type data for types in ultrait_wpl_properties:
select * from ultrait_wpl_property_types
where id in (select property_type from ultrait_wpl_properties);
You are getting a Cartesian result in the case the ultrait_wpl_property_types table has multiple records for a single property. Such as a property type could be Type A, Type B, Type C which might be descriptive "types". So a single property would be accounted for each entry.
You might just need to do SELECT DISTINCT, or GROUP BY ultrait_wpl_properties.id to make sure only one record per ID, but with generic "Select * ", I would first try with GROUP BY.

MySQL code to get one tables data, insert it into another and delete the old data

Info:
I need to create a MySQL code to select more than one lines of data from the table items_rooms, insert data into table items_users based from the data inside items_rooms THEN delete the data in items_rooms. But inside of that I need to also gather some data from another table items to grab the user Id of the owner who owns the item.
So in the end the only tables that have data are items and items_users, and they work from getting their data from items_rooms.
Seems confusing? I know, here is my code I wrote which I know is completely wrong but It might help you out.
$getItemRooms = $db->query("SELECT * FROM items_rooms WHERE room_id = '" . $roomid . "'");
while($roomitem = $getItemRooms->fetch_assoc()) {
$getItems = $db->query("SELECT * FROM items WHERE item_id = '" . $roomitem['item_id'] . "'");
while($items = $getItems->fetch_assoc()) {
$sql->query("INSERT INTO items_users (item_id, user_id) VALUES ('" . $roomitem['item_id'] . "', '" . $items['placedBy'] . "')");
$sql->query("DELETE FROM items_rooms WHERE room_id = '" . $roomid . "'");
echo 'done';
}
}
So for instance, room_id inside of items_rooms could be 3. inside items_rooms there are 10 rows if items that are owned. I need them items to be deleted and replaced into items_users but items_rooms does not have the owner id that items has.
One can use INSERT ... SELECT, together with an appropriate join:
INSERT INTO items_users (item_id, user_id)
SELECT item_id, items.placedBy
FROM items JOIN items_rooms USING (item_id)
WHERE room_id = ?
If your application is subject to synchronous database access from multiple clients, be careful to avoid a race hazard arising between the INSERT and DELETE statements; in particular consider using a locking read in the above statement and performing the DELETE statement within the same transaction.
If your main problem is grabbing data from items table try to retrieve all you need with one query using join.
For instance:
select *
from items_rooms as ir
inner join items as i on ir.item_id=i.item_id
where item_id = ...
It's better to specify only necessary fields from every table instead of using (*).
Also you can combine INSERT and SELECT statements into one query.
Try to look MySQL reference
It will simplify and speed up your php script

How do you format dates within MS Access Queries to prevent the US/UK issue

How do I ensure that I pick up the right number of records when filtering for dates within an Access Query:
SELECT ID, REF, SalesDate, DCount("ID","tblRecords"," Ref='" & [Ref] & "' AND [SalesDate]=#" & format([SalesDate],"yyyy/mm/dd") & "#") as EXPR1 from tblCurrent
It picks up the date ok if it cannot be misconstrued such as 28-04-12, but if it is 04-06-12 it doesn't pick it up as it's assuming it's the wrong way around.
Note that this query is not created on the fly or generated from a form etc...
I either use yyyy/mm/dd for dates in VBA:
#" & Format([SalesDate],"yyyy/mm/dd") & "#"
Or parameters, for building queries.
EDIT re additional information
Seeing you are using SQL server, I suggest you use a derived table, which you may find faster, for example:
SELECT dbo_Table_1.ADate, ACount FROM dbo_Table_1
LEFT JOIN (SELECT a.ADate,Count(*) As ACount
FROM dbo_Table_1 As a GROUP BY a.ADate) b
ON dbo_Table_1.Adate=b.ADate
EDIT re discussion
SELECT * FROM dbo_vwRecordsCurrent As t
LEFT JOIN (
SELECT a.OpptyIncentiveModifiedDate, a.DataSetID, Count(*) AS ACount
FROM dbo_vwRecordsHistorical AS a
WHERE a.OpportunityIgnored = True
GROUP BY a.OpptyIncentiveModifiedDate, a.DataSetID) AS h
ON t.OpptyIncentiveModifiedDate = h.OpptyIncentiveModifiedDate
AND t.DataSetID = h.DataSetID
I have aliased your tables as the names are very long, so to me, it is more readable to use aliases on the outer sql. They are essential in the inner sql. It is not a good idea to alias a derived table with the name of an existing table.