Could somebody please help me write a MySQL query to update some data I need to recreate from a corrupted source. Due to a programming error I’ve had to delete about 9000 row of corrupt data. I have a copy of the good data but can’t work out the joins to get the good data back into the repaired table.
I have 2 tables from a school with the following relevant columns
Table A – tbl_Lessons
Lesson_id
Lesson_class_id
Lesson_date
Lesson_term
Table B – tbl_Register
Register_id
Register_lesson_id
Register_student_id
Register_status
Register_update_by
Register_update_dat
So for each class_id there is a unique lesson_id for each date it is taught.
And for each lesson_id there is a unique register entry for each student taught.
All lessons from the current term had to be recreated and so the register for all lessons also had to be recreated.
Table C – Backup Data before deletion.
(Create table tbl_tmp_register as
select * from tbl_register inner join tbl_lessons on lesson_id = register_lesson_id
where lesson_term = "autumn 2019")
Lesson_id
Lesson_class_id
Lesson_date
Lesson_term
Register_id
Register_lesson_id
Register_student_id
Register_status
Register_update_by
Register_update_date
So what I would like to do is update Table B (register_status, register_update_by, register_update_date) with the data from the backup table. I know what it should be by looking in the backup table for the row that matches lesson_class_id , lesson_date & register_student_id but I cannot write the SQL to get the data copied across. I have tried and failed many times. I think this is quite close to update one field but it just seems to hang the server even if I narrow the register down to one class on one day.
update tbl_register as r inner join tbl_lessons as l on r.register_lesson_id = l.lesson_id,
(select register_student_status from tbl_tmp_register as TTR inner join tbl_lessons as L on L.lesson_class_id = TTR.lesson_class_id AND l.lesson_Date = TTR.Lesson_date) as tt
Set r.register_student_status = tt.register_student_status
where l.lesson_class_id = 000 and l.lesson_date = '2019-xx-yy';
If I try it another way with a more straight forward query I also hang the server.
update tbl_register as dest
inner join tbl_tmp_register as srce
on srce.register_student_id = dest.register_student_id
inner join tbl_lessons as otsrce
on otsrce.lesson_class_id = srce.lesson_class_id and otsrce.lesson_date = srce.lesson_date
set dest.register_student_status = srce.register_student_status
I know I'm close but not quite getting the joins right.
Any help much appreciated.
Edit with Sample data for NBK:
In the backup data set the register_id and the lesson_id are not identical to the new data set in the register and lesson tables as these have been regenerated so the link between the old and new is the student id, class id, and class date.
Sample data
Table A – lessons
Lesson_id:1
Lesson_class_id: 22
Lesson_date: 2019-09-01
Lesson_term: Autumn 2019
Table B- registers
Register_id:1
Register_lesson_id:1
Register_student_id:33
Register_status: NULL
Register_update_by: NULL
Register_update_dat: NULL
Register_id:2
Register_lesson_id:1
Register_student_id:44
Register_status: NULL
Register_update_by: NULL
Register_update_dat: NULL
…
Table C- Backup
Lesson_id: 555
Lesson_class_id: 1
Lesson_date: 2019-09-01
Lesson_term: Autumn 2019
Register_id: 666
Register_lesson_id: 1
Register_student_id: 33
Register_status: Present
Register_update_by: TeacherX
Register_update_date: 2019-09-02
Lesson_id: 556
Lesson_class_id: 1
Lesson_date: 2019-09-01
Lesson_term: Autumn 2019
Register_id: 667
Register_lesson_id: 1
Register_student_id: 44
Register_status: Late
Register_update_by: TeacherX
Register_update_date: 2019-09-02
Related
Now I am working with SQL files and have a question:
I would like to review the effect of the promotion campaign with the data in the sql file. In the SQL file there are 2 tables, web traffic and promotion campaign
The web traffic table, let's say table web are as follows
visitor_id purchase date traffic_source campaign_name country purchase_value
1 1/1/2018 Search promotion101 US 100
2 2/1/2018 Direct voucher02 UK 110
3 2/1/2018 Search buyme01 US 50
4 3/1/2018 Banner Example01 DE 130
.. ....... ... ... .. ...
And in the second table I have the campaign information, let's say table promotion
Promotion_date campaign_name num_delivered promotion_fee
1/12/2017 promotion101 50 30
2/12/2017 promotion101 30 20
2/12/2017 voucher02 40 10
3/12/2017 Example01 70 30
... ... ... ...
In this case, I tried to use the left join to merge the table first but the record duplicated
Select
web.campaign_name,
sum(web.promotion_fee),
sum(promotion.purchase_value)
FROM
web LEFT JOIN promotion
ON web.campaign_name = promotion.campaign_name
GROUP BY
1
However, it doesn't work because the left join simply duplicate the record...
In this case, If I want to formulate the table like this:
Campaign_name Traffic_source Total_Customer Total_purchase_value Total expenditure
promotion101 Search 1000 2000 1500
Example01 Banner 2000 3750 3000
Is it possible to do so? If yes then How can I make it?
Many thanks for your help in advance!
You may peform the aggregations of each table in separate subqueries:
SELECT
w.campaign_name,
w.purchase_value AS Total_purchase_value,
COALESCE(p.promotion_fee, 0) AS Total_expenditure
FROM
(
SELECT campaign_name, SUM(purchase_value) AS purchase_value
FROM web
GROUP BY campaign_name
) w
LEFT JOIN
(
SELECT campaign_name, SUM(promotion_fee) AS promotion_fee
FROM promotion
GROUP BY campaign_name
) p
ON w.campaign_name = p.campaign_name;
A critical assumption I have made here is that the web table contains data for all campaigns. If not, then you might have to join to a third table containing all campaigns which happened. Actually, arguably such a table should already exist.
i'm having some trouble with trying to extract some data from several MySQL tables in a join statement.
My tables and attributes are:
appointment_end_time (table)
appointment_end_time_id (int)(pk)(ai)
appointment_end_date (datetime)
appointment_start_time (table)
appointment_date_id (int)(pk)(ai)
appointment_start_date (datetime)
instructor(table)
instructor_id (int)(pk)(ai)
firstname varchar(45)
lastname varchar(45)
appointment_timetable
appointment_timetable_id int(11) AI PK
instructor_id int(11) FK
appointment_date_id int(11) FK
appointment_end_time_id int(11) FK
SELECT a.appointment_timetable_id, i.instructor_id, ad.appointment_start_date, aet.appointment_end_date
FROM db12405956.appointment_timetable a
JOIN instructor i on i.instructor_id = a.instructor_id
JOIN appointment_start_time ad on ad.appointment_date_id = a.appointment_date_id
JOIN appointment_end_time aet on aet.appointment_end_time_id = a.appointment_end_time_id
ORDER BY a.appointment_timetable_id;
However, this code brings back no rows selected when executed so i'm wondering what i'm doing wrong, any help will be much appreciated
Sample rows:
(appointment_end_time)
appointment_end_time_id appointment_end_date
1 2016-12-26 14:00:00
2 2016-12-24 13:00:00
3 2016-12-26 13:00:00
(appointment_start_time)
appointment_date_id appointment_start_date
1 2016-12-26 15:00:00
2 2016-12-24 16:00:00
3 2016-12-26 15:30:00
instructor_id firstname lastname
1 Sasha Thompson
2 Laura Robinson
3 John Walters
appointment_timetable
appointment_timetable_id instructor_id appointment_date_id appointment_end_time_
1 Blank Blank Blank
2 Blank Blank Blank
3 Blank Blank Blank
What you need is to learn how to diagnose the problem yourself. It is a common problem that a query doesn't return the expected results and you should understand how to break things down to find the issue.
Let's start with your query:
SELECT a.appointment_timetable_id, i.instructor_id, ad.appointment_start_date, aet.appointment_end_date
FROM db12405956.appointment_timetable a
JOIN instructor i on i.instructor_id = a.instructor_id
JOIN appointment_start_time ad on ad.appointment_date_id = a.appointment_date_id
JOIN appointment_end_time aet on aet.appointment_end_time_id = a.appointment_end_time_id
ORDER BY a.appointment_timetable_id;
What you do to break it down is start with the first table and then add the joins (and where conditions although you don't have any here), one at a time until the data problem appears. I find this easiest to do by using select * or select top 1 * (Or top 10 as I usually prefer to see more than one record) instead of the field list because then you don't have to look for the fields that are associated with joins you haven't added in yet.
So start with
SELECT top 10 *
FROM db12405956.appointment_timetable a
Then try
SELECT top 10 *
FROM db12405956.appointment_timetable a
JOIN instructor i on i.instructor_id = a.instructor_id
Then
SELECT top 10 *
FROM db12405956.appointment_timetable a
JOIN instructor i on i.instructor_id = a.instructor_id
JOIN appointment_start_time ad on ad.appointment_date_id = a.appointment_date_id
Finally
SELECT top 10 *
FROM db12405956.appointment_timetable a
JOIN instructor i on i.instructor_id = a.instructor_id
JOIN appointment_start_time ad on ad.appointment_date_id = a.appointment_date_id
JOIN appointment_end_time aet on aet.appointment_end_time_id = a.appointment_end_time_id
ORDER BY a.appointment_timetable_id;
At some point you will see where the records fell out and that is the location of the problem. Then you might need to look at the fields you are joining on and the data in them in your data sets to see why they are not returning any matches. For instance, if you are joining on dates, they may be stored as dates in one table and as varchar in another and date "01/01/2016' is not equal to 'Jan 1, 2016' or sometimes the column has some sort of prefix or suffix not in the other table. Something like PR2345 in one table and 2345 in the other. Sometimes the query is correct and no rows genuinely meet the conditions. This could be because the data is not fully populated yet (think writing a report for a system that is not live yet, no data on completed actions because none have completed yet.) or because the requirement was wrong in some of its assumptions or because there should be no matching records. It could even be a bug in the data entry.
Depending on the nature of the problem, you might need to return all the records or only use select top 1 (since all records are disappearing). Using SELECT * this way will help when you are returning too many or duplicate records as well as sometimes is is the fields not being returning that affect the results set. Note that I am not saying to use SELECT * in your final result set, it is only being used as a diagnostic tool here.
In your case, the problem looks as if it is in the first table. There are blanks for instructor ID and the other fields in your sample, so there is nothing to join on. (You only gave a sample so the rest of the table may not be like this.) If this is a case where the data is not there yet due to the feature that would add it not yet being live, then you can test your query only by adding test data to the table. Be sure to delete this data after you have finished unit testing. If the data should have been there, then you need to look at the insert from the application for a bug.
My end goal is to update information from table 1 to table 2 on a certain condition. More specifically, I'd like to update the date from table1 to table2 where the id's match and dates from table2 are NULL.
I want this to happen every Sunday.
Here are the specifics:
** Keep in mind, payee_id and id are the same but in two different tables. **
The table I plan to copy from is called orders, but I only want to select certain data from this table. My query looks like this:
TABLE 1
SELECT movement.payee_id,
min(origin_stop.sched_arrive_early) first_date
FROM orders
LEFT JOIN movement_order ON orders.id = movement_order.order_id
LEFT JOIN movement ON movement.id = movement_order.movement_id
LEFT JOIN stop as origin_stop ON origin_stop.id = movement.origin_stop_id
WHERE orders.status <> 'V'
GROUP BY movement.payee_id
OUTPUT 1
payee_id | first_date
-------------------|-----------------
STRINGID1 | 2013-12-20 15:00:00.000
STRINGID2 | 2013-12-27 13:00:00.000
TABLE 2
SELECT id, initial_date
FROM drs_payee
OUTPUT 2
id | initial_date
-------------------|-----------------
STRINGID1 | NULL
STRINGID2 | NULL
TABLE 2 OUTPUT SHOULD BE:
id | initial_date
-------------------|-----------------
STRINGID1 | 2013-12-20 15:00:00.000
STRINGID2 | 2013-12-27 13:00:00.000
My attempt to solve this:
UPDATE drs_payee a
(SELECT movement.payee_id,
min(origin_stop.sched_arrive_early) carrier_first_shipped_date
FROM orders
LEFT JOIN movement_order ON orders.id = movement_order.order_id
LEFT JOIN movement ON movement.id = movement_order.movement_id
LEFT JOIN stop as origin_stop ON origin_stop.id = movement.origin_stop_id
WHERE orders.status <> 'V'
GROUP BY movement.payee_id) b
ON a.id = b.payee_id
SET a.initial_date = b.first_date
WHERE a.initial_date IS NULL
Not sure if the format of this is correct and if you can even do a SELECT inside an UPDATE like shown above.
I believe I have to have a loop to find id's that match (i.e. where payee_id = id and initial_date is NULL). Would this be created in a stored procedure to loop through id's and create a weekly job schedule or would some type of update query be enough? Please help or point me in some direction with the an update query or stored procedure example using my data if possible.
Thanks in advance everyone!
For scheduled queries the best thing for me is creating events. First you have to select your db, and at the top right you'll see an option in phpmyadmin called "events". You have to turn on the events planner, and to do that you mut be logged in with a super privilege user, in phpMyadmin.
After you do that the query is:
DROP EVENT `dates update` ;
CREATE DEFINER = `your_user_name`#`your_host_name`
EVENT `dates update`
ON SCHEDULE EVERY1 WEEK STARTS '2015-07-29 03:00:00'
ON COMPLETION NOT PRESERVE ENABLE DO
UPDATE movement a
INNER JOIN orders b
ON a.payee_id = b.payee_id
SET a.initial_date = b.first_ship_date
WHERE a.initial_date IS NULL;
It must work.
If you need help about super privilege check this
I hope it works for you.
Caio Ortega
Update table2
inner join table1 on payee_id = id
set initial_date=first_date where initial_date is null
Through SQL server agent we can schedule the query as per our requirement (For example every Sunday )
I've got two tables in my MySQL DB. One contains requiredSkill1, requiredSkillLevel1, requiredSkill2, requiredSkillLevel2, requiredSkill3 and requiredSkillLevel3.
The other table has X rows per user with the following collumns: skill and level.
itemid requiredSkill1 requiredSkillLevel1 requiredSkill2 requiredSkillLevel2 requiredSkill3 requiredSkillLevel3
2410 3319 4 20211 1 NULL NULL
The other table:
userid skill level
21058 3412 4
21058 3435 2
21058 3312 4
Keep in mind, these are just examples.
I want every itemid which has matching values in requiredSkill{1-3} and requiredSkillLevel{1-3}.
Is this even possible with a single query and is this still performant, since the user table contains up to 300 rows per user and the item table has a fixed value of 6000 rows. This will be used in a web application, so I can use Ajax to load ranges of items from the database to decrease loading time.
I don't have the data set up. A SQL Fiddle would be helpful, but I think you want to approach it like this:
SELECT itemid FROM items i
INNER JOIN users u1 ON u1.skill = i.requiredSkill1 AND u1.level >= i.requiredSkillLevel1
INNER JOIN users u2 ON u2.skill = i.requiredSkill2 AND u2.level >= i.requiredSkillLevel2 AND u1.userid = u2.userid
INNER JOIN users u3 ON u3.skill = i.requiredSkill3 AND u3.level >= i.requiredSkillLevel3 AND u3.userid = u1.userid
Someone will solve this for you if you post demo data.
I have 2 Tables -- Table 1 is a master file and Table 2 is an activity file.
The relationship is 1-to-Many.
I am producing a report and all I want to return is every master file row joined to only the last activity row for the related master id.
I am unsure on how to request the last activity row. My code below returns every activity row (rightfully so).
Thank you for your help.
SELECT *
FROM master_file AS master
INNER JOIN activity_file AS activity ON activity.id = master.id
ORDER BY master.display_name
The activity file has a column called entry_date. It is a date and time stamp recording every activity. I simply want to select the last entry_date.
For example:
Table 2 - Activity looks like this
ID ACTIVITY ENTRY_DATE
1 Update 2012-08-01 09:00:00
1 Edit 2012-08-01 13:45:15
3 Create 2012-07-15 10:09:52
3 Delete 2012-07-22 23:02:00
3 Add 2012-08-05 04:33:00
4 Edit 2012-08-03 15:12:00
One standard way to solve this is to create an inline view that finds the last entry_date per ID.
SELECT *
FROM master_file AS master
LEFT JOIN activity_file AS activity ON activity.id = master.id
LEFT JOIN (select id , max(entry_date) entry_date
From activity_file
group by id) last_activity
ON activity_file.id = last_activity.id
and activity_file.entry_date= last_activity.entry_date
ORDER BY master.display_name
The one problem with this approach is that you may have more than one record with max(entry_date) for a given id. You'll either need to have your business rules handle this (e.g. simply display more than one record for that case) or you'll need to figure out a tie breaker. The last thing you want is to make it non-deterministic