Long time exection in update table with join in SQL server 2008 - 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.

Related

Subquery returns more than one row error when one row is returned

I am currently doing some SQL magic and wanted to update the stock in my companies ERP program. However if I try to run the following query I get the error mentioned in the title.
update llx_product lp
set stock = (select sum(ps.reel)
from llx_product_stock as ps, llx_entrepot as w
where w.entity IN (1)
and w.rowid = ps.fk_entrepot
and ps.fk_product = lp.rowid
group by ps.rowid)
The subquery by itself returns just one row if used with a rowid for the product.
select sum(ps.reel)
from llx_product_stock as ps, llx_entrepot as w
where w.entity in (1)
and w.rowid = ps.fk_entrepot
and ps.fk_product = 7372
group by ps.rowid
Any help would be appreciated
I would suggest writing the query as:
update llx_product lp
set stock = (select sum(ps.reel)
from llx_product_stock ps join
llx_entrepot w
on ps.fk_product = lp.rowid
where w.entity in (1) and
w.rowid = ps.fk_entrepot
);
An aggregation query with no group by cannot return more than one row. It is unclear how your version is returning more than one row because the key used in the group by also has an equality comparison. Perhaps there is some type conversion issue at play.
But in any case, without the group by, you cannot get the error you are currently getting.
For anyone wondering the solution to my issue was a very simple query, Gordon pointed in the right direction and I made it harder than it should be.
update llx_product lp
left join llx_product_stock ps on lp.rowid = ps.fk_product
set lp.stock = ps.reel

UPDATE query using multiple AND conditions slow in 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!

How to write update query using 2 tables and conditions

I am trying to update/revise the department names in a table called "DEPART_NAMES_AS_SUBMITTED" using another table called "DEPART_NAMES_REQUIRED." I would like this update to occur only if the line numbers in "DEPART_NAMES_AS_SUBMITTED" are within the line number range [LOW] [HIGH] in the second table called "DEPART_NAMES_REQUIRED." If the line number is less/more than the [LOW] [HIGH] range the department name should remain the same. I have unsuccessfully tried numerous SQLs including the following:
UPDATE DEPT_NAMES_SUBMITTED INNER JOIN DEPT_NAMES_REQUIRED ON(DEPT_NAMES_SUBMITTED.LINE_NUMBER = DEPT_NAMES_REQUIRED.HIGH) AND (DEPT_NAMES_SUBMITTED.LINE_NUMBER = DEPT_NAMES_REQUIRED.LOW) SET DEPT_NAMES_SUBMITTED.DEPART_NAME = [DEPT_NAMES_REQUIRED].[DEPART_NAME]
WHERE (((DEPT_NAMES_REQUIRED.LINE_NUMBER) Between [low] And [high]));
Thank you for taking the time to read and answer this question.
I think your query is fine if you remove the square braces and put in the right logic:
UPDATE DEPT_NAMES_SUBMITTED ns INNER JOIN
DEPT_NAMES_REQUIRED hr
ON ns.LINE_NUMBER <= nr.HIGH AND
ns.LINE_NUMBER >= nr.LOW
SET ns.DEPART_NAME = nr.DEPART_NAME;
Notice that table aliases make the query easier to write and to read.

Query execution was interrupted, error #1317

What I have is a table with a bunch of products (books, in this case). My point-of-sale system generates me a report that has the ISBN (unique product number) and perpetual sales.
I basically need to do an update that matches the ISBN from one table with the ISBN from the other and then add the sales from the one table to the other.
This needs to be done for about 30,000 products.
Here is the SQL statement that I am using:
UPDATE `inventory`,`sales`
SET `inventory`.`numbersold` = `sales`.`numbersold`
WHERE `inventory`.`isbn` = `sales`.`isbn`;
I am getting MySQL Error:
#1317 SQLSTATE: 70100 (ER_QUERY_INTERRUPTED) Query execution was interrupted
I am using phpMyAdmin provided by GoDaddy.com
I've probably come to this a bit late, but... It certainly looks like the query is being interrupted by an execution time limit. There may be no easy way around this, but here's a couple of ideas:
Make sure that inventory.isbn and sales.isbn are indexed. If they aren't, adding an index will reduce your execution time dramatically.
if that doesn't work, break the query down into blocks and run it several times:
UPDATE `inventory`,`sales`
SET `inventory`.`numbersold` = `sales`.`numbersold`
WHERE `inventory`.`isbn` = `sales`.`isbn`
AND substring(`inventory`.sales`,1,1) = '1';
The AND clause restricts the search to ISBNs starting with the digit 1. Run the query for each digit from '0' to '9'. For ISBNs you might find selecting on the last character gives better results. Use substring(inventory.sales,-1)`
try to use INNER JOIN in the two tables like that
UPDATE `inventory`
INNER JOIN `sales`
ON `inventory`.`isbn` = `sales`.`isbn`
SET `inventory`.`numbersold` = `sales`.`numbersold`
UPDATE inventory,sales
SET inventory.numbersold = sales.numbersold
WHERE inventory.isbn = sales.isbn
AND inventory.id < 5000
UPDATE inventory,sales
SET inventory.numbersold = sales.numbersold
WHERE inventory.isbn = sales.isbn
AND inventory.id > 5000 inventory.id < 10000
...
If the error, you can try to reduce the number to 1000, for example

Loop in MySql, or alternative?

I have a MySql db with innoDB tables. Very simplified this is how two tables are layed out:
Table A:
controlID(PK)
controlText
Table B:
controlOptionID(pk)
controlID(FK to table A)
controlOptionType
controlOptionValue
So many controlOptions(table B) can reference one control(giving that control multiple options). But for each option two rows are made in table B: one row with controlOptionType = "linkToCreator" and controlOptionValue = (an ID to the template it was made from*). And the other row type = "optionSelected" and value = "true"(or false).
= its a pretty complicated setup, but basically instead of set columns we are making dynamic ones by means of the type being what the column would have been called. So I couldnt link to the template with FK.
So now I need to select every control(which will have 2 controlOptions linking to it) where the one controlOptionValue value is true or false(depending on what i need) and the other controlOptionValue is an text ID that I specify.
What I think is the best way to do it is a
SELECT * FROM tableB WHERE controlOptionType = 'linkToCreator'
Then do a loop over that result set saying:
SELECT * FROM tableB WHERE tableB.controlID = (the controlID in this iterations row) AND tableB.controlValue = 'true'
But maybe thatls really inefficient, and either way I have no clue how to do that. It would be great if I could get a single query(i.e. not using stored procedures) that I specified templateID and true or false and it gave me a row result if it didn't find anything.
BTW this is for a search in our application with will need to go through TONS of rows so performance is paramount. And yes, I know the setup isnt the greatest...
Thanks :D
Like this?
SELECT * FROM tableA AS A
LEFT JOIN tableB AS ctrl1 ON (A.controlID = ctrl1.controlID AND ctrl1.controlOptionType = ? AND ctrl1.controlOptionValue = ?)
LEFT JOIN tableB AS ctrl2 ON (A.controlID = ctrl2.controlID AND ctrl2.controlOptionType = ? AND ctrl2.controlOptionValue = ?)
Try this:
SELECT *
FROM Table_A
LEFT JOIN Table_B
ON Table_A.ControlID = Table_B.ControlID
WHERE Table_A.controlOptionType = 'linkToCreator