Mysql update using values from select - mysql

I have two queries. The first will return multiple rows:
SELECT parent_entry_id,child_entry_id FROM exp_playa_relationships WHERE parent_field_id = '34';
...And I would like to use the values (parent_entry_id,child_entry_id) and incorporate them into this query, replacing 'x' and 'y', and do it for each row returned by the first query.
UPDATE exp_channel_data AS t1,
(
SELECT field_id_46,field_id_47 FROM exp_channel_data WHERE entry_id = 'x') AS t2
SET t1.field_id_60 = t2.field_id_46, t1.field_id_61 = t2.field_id_47
WHERE t1.entry_id = 'y';
I think I need to use another JOIN, but I can't figure out how to implement one in my example. Any help would be much appreciated.

I think this is what you're after:
UPDATE exp_playa_relationships AS t0
JOIN exp_channel_data AS t1
ON t1.entry_id = t0.child_entry_id
JOIN exp_channel_data AS t2
ON t2.entry_id = t0.parent_entry_id
SET t1.field_id_60 = t2.field_id_46
, t1.field_id_61 = t2.field_id_47

Try this query
UPDATE exp_channel_data a1 INNER JOIN exp_playa_relationships a ON a1.entry_id = a.child_entry_id
INNER JOIN exp_channel_data b ON a.parent_entry_id = b.entri_id
SET a1.field_id_60 = b.field_id_46, ta1.field_id_61 = b.field_id_47
WHERE parent_field_id = '34'

Thanks all for your replies. The working syntax is:
UPDATE exp_channel_data AS t1,
(
SELECT
entry_id as ei2, child_entry_id, parent_entry_id, field_id_46 as f46,field_id_47 as f47
FROM
exp_channel_data JOIN exp_playa_relationships ON entry_id=child_entry_id AND parent_field_id = 34) AS t2
SET t1.field_id_60 = f46, t1.field_id_61 = f47
WHERE t1.entry_id=parent_entry_id;

Or in a more classic syntax, you need to adjust to your own foo & bar attributes, but use something like the following:
update exp_channel_data t1
set (t1.field_id_60,t1.field_id_61) = (
select t2.field_id_46 , t2.field_id_47
from exp_channel_data t2
where 1=1
and t2.entry_id = 'x'
and /* ENTER YOUR t1-t2 join condition here */
)
where 1=1
and t1.entry_id = y
;
But since you are MySQL I don't believe it supports compound subquery. As such:
update exp_channel_data t1
set t1.field_id_60 = (
select t2.field_id_46
from exp_channel_data t2
where 1=1
and t2.entry_id = 'x'
and /* ENTER YOUR t1-t2 join condition here */
) , t1.field_id_61 = (
select t3.field_id_47
from exp_channel_data t3
where 1=1
and t3.entry_id = 'x'
and /* ENTER YOUR t1-t3 join condition here */
)
where 1=1
and t1.entry_id = y
;

Related

magento2 mysql update table query

If someone can help with this MySQL query that would be great
I want to update this table
UPDATE catalog_product_entity_int
This query brings an array of values and works.
select catalog_product_entity.sku,catalog_product_relation.parent_id,catalog_product_flat_1.special_price
from catalog_product_entity
left join catalog_product_relation on (catalog_product_entity.entity_id = catalog_product_relation.parent_id)
left join catalog_product_flat_1 on (catalog_product_flat_1.entity_id = catalog_product_relation.child_id)
where catalog_product_entity.type_id = "configurable"
and catalog_product_flat_1.special_price > 1
GROUP BY catalog_product_relation.parent_id;
This is what I want to set based on the above query
SET catalog_product_entity_int.value = 1
where catalog_product_entity_int.attribute_id ='579'
and catalog_product_relation.parent_id = catalog_product_entity_int.entity_id
I'm not sure if I need to get the select query into a temp table first and if so how?
Theeasiest way is to join both table
i added aliases for he table to make it more readable
UPDATE catalog_product_entity_int t1,(select catalog_product_entity.sku,catalog_product_relation.parent_id,catalog_product_flat_1.special_price
from catalog_product_entity
left join catalog_product_relation on (catalog_product_entity.entity_id = catalog_product_relation.parent_id)
left join catalog_product_flat_1 on (catalog_product_flat_1.entity_id = catalog_product_relation.child_id)
where catalog_product_entity.type_id = "configurable"
and catalog_product_flat_1.special_price > 1
GROUP BY catalog_product_relation.parent_id) t2
SET t1.value = 1
where t1.attribute_id ='579'
and t2.parent_id = t1.entity_id
catalog_product_entity.sku and catalog_product_flat_1.special_price aren't used in the update and so you should check if they are needed
Try the select query
SELECT t1.value, t1.entity_id
FROM
catalog_product_entity_int t1 INNER JOIN (select catalog_product_entity.sku,catalog_product_relation.parent_id,catalog_product_flat_1.special_price
from catalog_product_entity
left join catalog_product_relation on (catalog_product_entity.entity_id = catalog_product_relation.parent_id)
left join catalog_product_flat_1 on (catalog_product_flat_1.entity_id = catalog_product_relation.child_id)
where catalog_product_entity.type_id = "configurable"
and catalog_product_flat_1.special_price > 1
GROUP BY catalog_product_relation.parent_id) t2
ON t2.parent_id = t1.entity_id
where t1.attribute_id ='579'
Thank you for the help. In the end this is what i did to make it work.
First create a temp table to store the values of the query
CREATE TABLE on_sale_updating AS
select catalog_product_entity.sku,catalog_product_relation.parent_id,catalog_product_flat_1.special_price
from catalog_product_entity
left join catalog_product_relation on (catalog_product_entity.entity_id = catalog_product_relation.parent_id)
left join catalog_product_flat_1 on (catalog_product_flat_1.entity_id = catalog_product_relation.child_id)
where catalog_product_entity.type_id = "configurable"
and catalog_product_flat_1.special_price > 1
and catalog_product_flat_1.special_to_date IS NULL OR catalog_product_flat_1.special_to_date >= CURDATE()
GROUP BY catalog_product_relation.parent_id;
Then run an update query against the temp table
update catalog_product_entity_int
inner join on_sale_updating ON catalog_product_entity_int.entity_id = on_sale_updating.parent_id
SET catalog_product_entity_int.value = 1
where catalog_product_entity_int.attribute_id ='579'
Once run for the first time add
DROP TABLE on_sale_updating;
to the first part.

How acomplish a result from third Inner Join in mySQL- statement

I use MySQL database.
I run this question today
SELECT t1.catalogID, t2.antfrp, t1.Latin, t1.Popular
FROM `mydb`.`products` T1
INNER JOIN `mydb`.`packages` T2 ON T1.catalogID = T2.catalogID
WHERE T1.Spring = 1
AND T1.lager + T1.sold > 0
AND (T2.packtyp = "L" OR T2.packtyp = "P")
It results in a several thousand rows long RecordSet. In the same RecordSet - I want this question from a third table to be included as an extra field in each row
SELECT SUM(Numitems)
from oitems
WHERE
catalogid = (the actual one for each row) AND
orderid > 25746 AND (packtyp = "L" OR packtyp = "P") AND
numitems = 1
and have for that purpose made a third Inner JOIN like this
INNER JOIN `mydb`.`oitems` T3
ON T3.catalogid = T2.catalogID
And altered my SELECT to
SELECT t1.catalogID, t2.antfrp, t1.Latin, t1.Popular, (SELECT SUM(T3.Numitems)
from oitems AS T3
WHERE T3.orderid > 25746 AND
(T3.packtyp = "L" OR T3.packtyp = "P") AND T3.numitems = 1)
However - that is not the correct way to do it - and I feel stucked and can not wrap my head around how to accomplish this - Can someone with a better MySQL understanding perhaps see where I go wrong??
You should join and do the fact you are using aggregation function you should use group by for t1.catalogID, t2.antfrp, t1.Latin, t1.Popular
SELECT SUM(T3.Numitems) , t1.catalogID, t2.antfrp, t1.Latin, t1.Popular
FROM `mydb`.`products` T1
INNER JOIN `mydb`.`packages` T2 ON T1.catalogID = T2.catalogID
INNER JOIN oitems T3 ON T3.catalogid = T1.catalogid
WHERE T1.Spring = 1
AND T1.lager + T1.sold > 0
AND (T2.packtyp = "L" OR T2.packtyp = "P")
AND T3. orderid > 25746 AND (T3.packtyp = "L" OR T3.packtyp = "P") AND T3.numitems = 1
GROUP BY t1.catalogID, t2.antfrp, t1.Latin, t1.Popular
You probably want to join to a subquery on the third table:
SELECT
t1.catalogID,
t2.antfrp,
t1.Latin,
t1.Popular,
t3.numitems
FROM products t1
INNER JOIN packages t2
ON t1.catalogID = t2.catalogID
INNER JOIN
(
SELECT catalogID, SUM(Numitems) AS Numitems
FROM oitems
WHERE
orderid > 25746 AND
(packtyp = 'L' OR T3.packtyp = 'P') AND
numitems = 1
GROUP BY catalogID
) t3
ON t2.catalogID = t3.catalogID
WHERE
t1.Spring = 1 AND
t1.lager + t1.sold > 0 AND
(t2.packtyp = 'L' OR t2.packtyp = 'P');

Specific query optimization on MySQL

I have a table into MySQL DB (version 5.1.x), with the name table. Its columns are:
id, double_col_index1, double_col_index2, flag, col_index_1, a_date_col, col_index_2, col_index_3 with the following indexes:
a single index on double_col_index1 and double_col_index2
an index on col_index_1
an index on col_index_2
an index on col_index_3
Now, I have the following query:
UPDATE `table` t1 INNER JOIN
(SELECT t2.id FROM `table` t2
WHERE t2.double_col_index1 = 'fake_value1'
AND t2.double_col_index2 = 'fake_value2'
AND flag = 'true'
AND (col_index_1 = '' OR a_date_col < '1920-11-10 00:00:00')
AND
(SELECT count(t3.id) FROM `table` t3
WHERE t3.double_col_index1 = 'fake_value1'
AND t3.double_col_index2 = 'fake_value2'
AND t3.col_index_2 = t2.col_index_2
AND t3.col_index_3 = 'fake_col_index_3_1') > 0
AND
(SELECT count(t4.id) FROM `table` t4
WHERE t4.double_col_index1 = 'fake_value1'
AND t4.double_col_index2 = 'fake_value2'
AND t4.col_index_2 = t2.col_index_2
AND t4.col_index_3 = 'fake_col_index_3_2') > 0) tbl
ON t1.id = tbl.id SET col_index_1 = 'fake_value';
Question: I would need to improve this query, to give a better performance if possible. Would anyone have any suggestions on this?
One idea would be to use instead of INNER JOIN an t1.id in (.... What is your advice on this?
Basic idea of the join would be to do it as follows.
UPDATE `table` t1
INNER JOIN
(
SELECT t2.id
FROM `table` t2
INNER JOIN
(
SELECT DISTINCT col_index_2
FROM `table`
WHERE double_col_index1 = 'fake_value1'
AND double_col_index2 = 'fake_value2'
AND col_index_3 = 'fake_col_index_3_1'
) t3
ON t3.col_index_2 = t2.col_index_2
INNER JOIN
(
SELECT DISTINCT col_index_2
FROM `table`
WHERE double_col_index1 = 'fake_value1'
AND double_col_index2 = 'fake_value2'
AND col_index_3 = 'fake_col_index_3_2'
) t4
ON t4.col_index_2 = t2.col_index_2
WHERE t2.double_col_index1 = 'fake_value1'
AND t2.double_col_index2 = 'fake_value2'
AND flag = 'true'
AND (col_index_1 = '' OR a_date_col < '1920-11-10 00:00:00')
) tbl
ON t1.id = tbl.id
SET col_index_1 = 'fake_value';
This may be quite a bit quicker but will depend on many factors. MySQL will not use indexes for joining against the sub queries.
However there is a big issue with this (and your existing query) in MySQL
http://dev.mysql.com/doc/refman/5.7/en/update.html
Currently, you cannot update a table and select from the same table in a subquery.
There is a way round this, by doing a query on the sub query

MySQL error: duplicate column

I'm having a bit of a problem with the following MySQL query and I can't find the source of it.
MySQL tells me that
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name
'annonce_dispo_id'
SELECT MAX(max_price) AS `max_price`,
COUNT(*) AS `nb_annonces`,
SUM(nb_dispo) AS `nb_dispo`
FROM
(SELECT `annonce`.`id`,
CEIL(MAX(price)*1.16) AS `max_price`,
COUNT(DISTINCT annonce.id) AS `nb_annonces`,
COUNT(annonce_dispoo.annonce_dispo_id) AS `nb_dispo`,
`annonce_dispo1`.*,
`annonce_dispo2`.*
FROM `annonce`
LEFT JOIN `annonce_dispo` AS `annonce_dispoo` ON (annonce_dispoo.annonceId = annonce.id
AND STR_TO_DATE(annonce_dispoo.dispo_date, '%d/%m/%Y') >= CURDATE())
INNER JOIN `annonce_dispo` AS `annonce_dispo1` ON annonce.id = annonce_dispo1.annonceId
INNER JOIN `annonce_dispo` AS `annonce_dispo2` ON annonce.id = annonce_dispo2.annonceId
WHERE ((annonce.city IN
(SELECT `cities`.`id`
FROM `cities`
WHERE (cities.label LIKE 'lyon%'))
OR annonce.zipcode = 'lyon')
OR (annonce.city LIKE '28674'
OR annonce.zipcode = '28674'))
AND (annonce_dispo1.dispo_date = '27/05/2014')
AND (annonce_dispo1.disponibility = 'available')
AND (annonce_dispo2.dispo_date = '31/05/2014')
AND (annonce_dispo2.disponibility = 'available')
AND (annonce.visible = 1)
AND (annonce.completed = 1)
GROUP BY `annonce`.`id` HAVING (nb_dispo >= 1)) AS `t`
I thought gave a different alias for the table in each JOIN I use them in, and can't really put my finger on what else is possible to output such an error.
Don't select annonce_dispo1.* and annonce_dispo2.* in your subquery, duplicated column names are being returned. Instead select the fields you need and alias accordingly.
SELECT MAX(max_price) AS `max_price`,
COUNT(*) AS `nb_annonces`,
SUM(nb_dispo) AS `nb_dispo`
FROM
(SELECT `annonce`.`id`,
CEIL(MAX(price)*1.16) AS `max_price`,
COUNT(DISTINCT annonce.id) AS `nb_annonces`,
COUNT(annonce_dispoo.annonce_dispo_id) AS `nb_dispo`,
`annonce_dispo1`.field, `annonce_dispo1`.otherfield,
`annonce_dispo1`.field as field2, `annonce_dispo1`.otherfield as otherfield2
FROM `annonce`
LEFT JOIN `annonce_dispo` AS `annonce_dispoo` ON (annonce_dispoo.annonceId = annonce.id
AND STR_TO_DATE(annonce_dispoo.dispo_date, '%d/%m/%Y') >= CURDATE())
INNER JOIN `annonce_dispo` AS `annonce_dispo1` ON annonce.id = annonce_dispo1.annonceId
INNER JOIN `annonce_dispo` AS `annonce_dispo2` ON annonce.id = annonce_dispo2.annonceId
WHERE ((annonce.city IN
(SELECT `cities`.`id`
FROM `cities`
WHERE (cities.label LIKE 'lyon%'))
OR annonce.zipcode = 'lyon')
OR (annonce.city LIKE '28674'
OR annonce.zipcode = '28674'))
AND (annonce_dispo1.dispo_date = '27/05/2014')
AND (annonce_dispo1.disponibility = 'available')
AND (annonce_dispo2.dispo_date = '31/05/2014')
AND (annonce_dispo2.disponibility = 'available')
AND (annonce.visible = 1)
AND (annonce.completed = 1)
GROUP BY `annonce`.`id` HAVING (nb_dispo >= 1)) AS `t`
See here for an example that doesn't work:
http://sqlfiddle.com/#!2/9bb13/1
The problem is that you are selecting all columns in the tables annonce_dispo1 and annonce_dispo2.
The fact that you have attributed different table names doesn't mean that there aren't duplicate column names.
I mean, you should use [Table name].[column name]
Example:
(SELECT `annonce`.`id`,
CEIL(MAX(price)*1.16) AS `max_price`,
COUNT(DISTINCT annonce.id) AS `nb_annonces`,
COUNT(annonce_dispoo.annonce_dispo_id) AS `nb_dispo`,
`annonce_dispo1`.annonce_dispo_id AS `column1`,
`annonce_dispo2`.annonce_dispo_id AS `column2`
I hope I've helped

Update mysql rows with value extracted from counting another table

I have the following query:
SELECT int_intrebari.id, COUNT( id_raspuns ) AS nr_raspunsuri
FROM int_intrebari, int_raspunsuri
WHERE int_intrebari.id = int_raspunsuri.id
GROUP BY id
Is it possible to update first table with nr_raspunsuri from the query, without writing a foreach statement?
You can UPDATE with JOIN like so:
UPDATE int_intrebari i1
INNER JOIN
(
SELECT id, COUNT( id_raspuns ) AS nr_raspunsuri
FROM int_intrebari
GROUP BY id
) i2 ON i1.id = i2.id
SET i1.nr_raspunsuri = i2.nr_raspunsuri
You can do it like -
update int_intrebari left join int_raspunsuri on int_intrebari.id =int_raspunsuri.id
set int_intrebari.column_to_update = int_raspunsuri.column_from_update_second_table
UPDATE
(SELECT int_intrebari.id, COUNT( id_raspuns) AS nr_raspunsuri
FROM int_intrebari, int_raspunsuri
WHERE int_intrebari.id = int_raspunsuri.id
GROUP BY id) t1,
int_raspunsuri t2
SET
t2.nr_raspunsuri=t1.nr_raspunsuri
WHERE
t1.id=t2.id