UPDATE query using multiple AND conditions slow in MYSQL - mysql

I am trying to update a table (~2 million rows) based on another table(10k rows). However, my update query is taking extremely long(30 mins) without any outputs as of yet. Is there a way to optimise this query?
UPDATE global_mobility_report
SET
global_mobility_report.locationID1 = (SELECT
geography.locationID
FROM
geography
WHERE
global_mobility_report.country_region = geography.country_region
AND global_mobility_report.sub_region_1 = geography.sub_region_1
AND global_mobility_report.sub_region_2 = geography.sub_region_2
AND global_mobility_report.metro_area = geography.metro_area
AND global_mobility_report.iso_3166_2_code = geography.iso_3166_2_code
AND global_mobility_report.census_fips_code = geography.census_fips_code);

UPDATE global_mobility_report
JOIN geography USING ( country_region,
sub_region_1,
sub_region_2,
metro_area,
iso_3166_2_code,
census_fips_code )
SET global_mobility_report.locationID1 = geography.locationID;
The presence of according index will improve.
The rows in global_mobility_report which have no according row in geography will not be updated (stay unchanged). If you need them to be set to NULL then use LEFT JOIN.

I simply indexed the country_region,
sub_region_1,
sub_region_2,
metro_area,
iso_3166_2_code,
census_fips_code columns and it worked like a charm!

Related

Update Query taking long to run

I need some assistance with a query I am using (MySQL) to update another table. When running the nested query, the query runs in less than a second. But as soon as I include the update part, it takes hours to run. The query I am using is as per the below:
UPDATE sys_reference.outlet_reference OUTREF LEFT JOIN
(SELECT
store_code 'storeCode'
, LEFT(header_value,20) 'CoOrds'
FROM
am_data_warehouse.am_headers
WHERE
action_date = CURDATE()- 1
AND header_field_id IN (3641, 4937)
) GPSCO
ON OUTREF.store_code = GPSCO.storeCode
SET OUTREF.gps_coordinates = GPSCO.CoOrds
Below is the structure of the table that is being updated:
I think the sub-query isn't doing you any favors here. I think you can rewrite it to elimiate the sub-query.
UPDATE
sys_reference.outlet_reference AS OUTREF
INNER JOIN am_data_warehouse.am_headers AS GPSCO ON OUTREF.store_code =
GPSCO.storeCode
SET
OUTREF.gps_coordinates = LEFT(GPSCO.header_value,20)
WHERE
GPSCO.action_date = CURDATE() - 1
AND GPSCO.header_field_id IN (3641, 4937)

MySQL Query gets too complex for me

I'm trying to write a MYSQL Query that updates a cell in table1 with information gathered from 2 other tables;
The gathering of data from the other 2 tables goes without much issues (it is slow, but that's because one of the 2 tables has 4601537 records in it.. (because all the rows for one report are split in a separate record, meaning that 1 report has more than 200 records)).
The Query that I use to Join the two tables together is:
# First Table, containing Report_ID's: RE
# Table that has to be updated: REGI
# Join Table: JT
SELECT JT.report_id as ReportID, REGI.Serienummer as SerialNo FROM Blancco_Registration.TrialTable as REGI
JOIN (SELECT RE.Value_string, RE.report_id
FROM Blancco_new.mc_report_Entry as RE
WHERE RE.path_id=92) AS JT ON JT.Value_string = REGI.Serienummer
WHERE REGI.HardwareType="PC" AND REGI.BlanccoReport=0 LIMIT 100
This returns 100 records (I limit it because the database is in use during work hours and I don't want to steal all resources).
However, I want to use these results in a Query that updates the REGI table (which it uses to select the 100 records in the first place).
However, I get the error that I cannot select from the table itself while updateing it (logically). So I tried selecting the select statement above into a temp table and than Update it; however, then I get the issue that I get to much results (logically! I only need 1 result and get 100) however, I'm getting stuck in my own thougts.. I ultimately need to fill the ReportID into each record of REGI.
I know it should be possible, but I'm no expert in MySQL.. is there anybody that can point me into the right direction?
Ps. fixing the table containing 400k records is not an option, it's a program from an external developer and I can only read that database.
The errors I'm talking about are as follows:
Error Code: 1093. You can't specify target table 'TrialTable' for update in FROM clause
When I use:
UPDATE TrialTable SET TrialTable.BlanccoReport =
(SELECT JT.report_id as ReportID, REGI.Serienummer as SerialNo FROM Blancco_Registration.TrialTable as REGI
JOIN (SELECT RE.Value_string, RE.report_id
FROM Blancco_new.mc_report_Entry as RE
WHERE RE.path_id=92) AS JT ON JT.Value_string = REGI.Serienummer
WHERE REGI.HardwareType="PC" AND REGI.BlanccoReport=0 LIMIT 100)
WHERE TrialTable.HardwareType="PC" AND TrialTable.BlanccoReport=0)
Then I tried:
UPDATE TrialTable SET TrialTable.BlanccoReport = (SELECT ReportID FROM (<<and the rest of the SQL>>> ) as x WHERE X.SerialNo = TrialTable.Serienummer)
but that gave me the following error:
Error Code: 1242. Subquery returns more than 1 row
Haveing the Query above with a LIMIT 1, gives everything the same result
Firstly, your query seems to be functionally identical to the following:
SELECT RE.report_id ReportID
, REGI.Serienummer SerialNo
FROM Blancco_Registration.TrialTable REGI
JOIN Blancco_new.mc_report_Entry RE
ON RE.Value_string = REGI.Serinummer
WHERE REGI.HardwareType = "PC"
AND REGI.BlanccoReport=0
AND RE.path_id=92
LIMIT 100
So, why not use that?
EDIT:
I still don't get it. I can't see what part of the problem the following fails to solve...
UPDATE TrialTable REGI
JOIN Blancco_new.mc_report_Entry RE
ON RE.Value_string = REGI.Serinummer
SET TrialTable.BlanccoReport = RE.report_id
WHERE REGI.HardwareType = "PC"
AND REGI.BlanccoReport=0
AND RE.path_id=92;
(This is not an answer, but maybe a pointer towards a few points that need further attention)
Your JT sub query looks suspicious to me:
(SELECT RE.Value_string, RE.report_id
FROM Blancco_new.mc_report_Entry as RE
WHERE RE.path_id=92
GROUP BY RE.report_id)
You use group by but don't actually use any aggregate functions. The column RE.Value_string should strictly be something like MAX(RE.Value_string) instead.

Update using Select Statement

I wanna write a query like this :
UPDATE `test_credit`
SET `test_credit`.`credit`=(`test_credit`.`credit`-((`test_credit`.`credit`/100)*5))
WHERE `test_credit`.`name` = `users`.`uname`
in fact i want to get a query on users.uname = test_credit.name but mysql say it has error and realize users.uname as column
what is correct query ?
You need to explicitly join it with table users. As far from my understanding based on your query, you want to calculate the credit if the names exists on both tables.
Give this a try,
UPDATE test_credit a
INNER JOIN users b
ON a.name = b.uname
SET a.credit = (a.credit - ((a.credit/100) * 5.0))
-- WHERE b.parent= "example"

Long time exection in update table with join in SQL server 2008

i'm facing a big problem when trying to update a table containing stock data put in join with a table containing product classification. This operation is taking long time for execution.
Table dw_giacenze (having flag_nomatch parameter equal to T) a is put on inner join with dw_key_prod z on ecat_key field.
a contains up to 3 milions records, z 150k records.
It takes more than 2 hours in execution.
Below the update query I'm using.
update dw_giacenze
set cate_ecat_key = z.cate_ecat_key,
sottocat_ecat_key = z.sottocat_ecat_key,
marchio_key = z.marchio_key,
sottocat_bi_key = z.sottocat_bi_key,
gruppo_bi_key = z.gruppo_bi_key,
famiglia_bi_key = z.famiglia_bi_key,
flag_nomatch = NULL
from dw_giacenze a
inner join dw_key_prod z on
z.ecat_key = a.ecat_key
where
a.flag_nomatch = 'T';
Can anyone help me in optimizing it?
Thanks in advance!
Enrico
I would suggest focusing in on a.flag_nomatch = 'T'.
A great way to get a really clear picture of what's going on is to use SQL Server Profiler. If this shows that your reads equals the number of rows in the table, then that's definitely an issue. Adding an index on flag_nomatch.
Alternatively, you could separate this out and update things individually (to start with)
UPDATE dw_giacenze
set sottocat_ecat_key = (SELECT sottocat_ecat_key
FROM dw_key_prod
WHERE dw_key_prod.ecat_key = dw_giacenze.ecat_key)
where
dw_giacenze.flag_nomatch = 'T';
I did notice that the first parameter in your set statement is actually the same parameter in your join. That means that you are setting it to the same exact value, so you should be able to remove that anyway.

how to update one table using data from second table

I am bit stuck with this one.. what i want is update app_name (first table). It returns no error.. but does nothing...
UPDATE tbl_m_app AS tma, tbl_measure AS tm
SET tma.app_name='Ap1'
WHERE (tm.mesure_id = tma.mesure_id
AND tm.live = 1)
This query will do the same work in more obvious way and without joins
UPDATE tbl_m_app AS tma
SET tma.app_name='Ap1'
WHERE tma.mesure_id IN (SELECT tm.mesure_id FROM tbl_measure AS tm WHERE tm.live = 1)
I think this SQL is fine, it's just not matching any rows.
Check this by using a select with the same where clause:
SELECT * FROM tbl_measure tm WHERE tm.live=1;
0 rows returned, right?