Update rows based on WHERE from INNER JOIN - mysql

I need to update a column's value when a row exists based on multiple conditions within a join. I've got the following:
SELECT *
FROM Fixtures f
INNER JOIN Results r ON f.FixtureID = r.FixtureID
WHERE f.Status = 1
AND f.IsResult = 0
AND f.Season = 1
AND r.TeamID IS NOT NULL
AND (DATEDIFF(NOW(), f.Date) >= 2)
Which returns a single row that matches, I'd like to then update f.IsResult so have done the following:
UPDATE f
SET f.IsResult = 1
FROM Fixtures f
INNER JOIN Results r ON f.FixtureID = r.FixtureID
WHERE f.Status = 1
AND f.IsResult = 0
AND f.Season = 1
AND r.TeamID IS NOT NULL
AND (DATEDIFF(NOW(), f.Date) >= 2)
However I get an error when trying this #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM Fixtures f INNER JOIN Results r ON f.FixtureID = r.FixtureID WHERE f.S' at line 3

Try this:
UPDATE Fixtures
SET Fixtures.IsResult = 1
WHERE Fixtures.Status = 1
AND Fixtures.IsResult = 0
AND Fixtures.Season = 1
AND (SELECT TeamID FROM Results WHERE Fixtures.FixtureID = Results.FixtureID) IS NOT NULL
AND (DATEDIFF(NOW(), Fixtures.Date) >= 2)
By using (Results) in a subquery, UPDATE statement has a single table (Fixtures) to target.

Related

SQL noob trying to do update query with join

I’m trying to run an update query which I’ll run daily, unfortuntately I suck at SQL and have no clue what to do with the join functions. I keep getting invalid group error. I took the table names out
Managed to narrow down the issue (this is in SQLYog btw)
UPDATE CMCDAR
SET cmcdar.effective_exposure_in_global_currency = (mcdar.A_Rbalance - SUM(CASE
WHEN eps.fk_account_id = '90059' AND eps.sent_to_erp = '0' THEN (eps.transaction_amount) ELSE 0 END))
FROM eps
JOIN cmcdar ON eps.fk_customer_map_id = cmcdar.fk_customer_map_id
JOIN mcdar ON eps.fk_customer_map_id = mcdar.fk_customer_map_id
JOIN mcar ON eps.fk_customer_map_id = mcar.pk_customer_map_id
WHERE cmcdar.is_deleted = 0
AND mcar.is_deleted = 0
AND mcdar.is_deleted = 0
GROUP BY eps.fk_customer_map_id;
without Group by it returns it all as one bi
g row, with group by it fails. Interestingly with + rather than - in the sum it seems to seperate it even without group by. Any workarounds for group by?
Your syntax is off - see here:SQL Update with a Join
UPDATE
t1
SET
t1.c1 = t2.c2,
t1.c2 = expression,
...
FROM
t1
[INNER | LEFT] JOIN t2 ON join_predicate
WHERE
where_predicate;
I would assume move the join into from clause.
UPDATE cmcdar
SET effective_exposure_in_global_currency = (mcdar.A_Rbalance - SUM(CASE WHEN eps.fk_account_id =
'90059' AND eps.sent_to_erp = '0' THEN (eps.transaction_amount) ELSE 0 END))
from cmcdar
JOIN eps ON cmcdar.fk_customer_map_id = eps.fk_customer_map_id
JOIN mcar ON cmcdar.fk_customer_map_id = mcar.pk_customer_map_id
JOIN mcdar ON cmcdar.fk_customer_map_id = mcdar.fk_customer_map_id
WHERE cmcdar.is_deleted = 0
AND cmcdar.fk_customer_map_id = eps.fk_customer_map_id
AND mcar.is_deleted = 0
AND mcdar.is_deleted = 0
AND cmcdar.fk_account_id = '90059'
AND mcdar.fk_account_id = '90059';

How can i update the results of a MySQL select query

I have the following SELECT query...
SELECT users.id, users.firstname, users.lastname, users.email,
users.live, users.editoverride,
usertenderstage.tenderId,
usertenderstage.stageId, usertenderstage.statusId
FROM users
JOIN usertenderstage ON usertenderstage.userId = users.id
WHERE users.live = 1 AND usertenderstage.tenderId = 1
AND usertenderstage.stageId = 2 AND usertenderstage.statusid = 6
I am trying to edit the query to make it an UPDATE query, and set users.editoverride = 1. My attempt is below...
UPDATE users.id, users.firstname, users.lastname, users.email,
users.live, users.editoverride,
usertenderstage.tenderId,
usertenderstage.stageId, usertenderstage.statusId
FROM users
JOIN usertenderstage ON usertenderstage.userId = users.id
SET users.editOverride = 1
WHERE users.live = 1 AND usertenderstage.tenderId = 1
AND usertenderstage.stageId = 2 AND usertenderstage.statusid = 6
But I am getting error message
#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'FROM users
JOIN usertenderstage ON usertenderstage.userId = users.id
SET users' at line 5
Could someone please help me to know what I'm doing wrong? Thanks.
Following should work:
UPDATE users
SET editoverride = 1
WHERE id IN
(SELECT users.id
FROM users
JOIN contractorscontractsappliedfor ON contractorscontractsappliedfor.contractorId = users.id
JOIN usertenderstage ON usertenderstage.userId = users.id
WHERE users.live = 1
AND contractorscontractsappliedfor.contractid = 1
AND usertenderstage.stageId = 2
AND usertenderstage.statusid = 6)
It seems the issue is with MySQL as you are getting error "#1093 - You can't specify target table 'users' for update in FROM clause". To get around, nest it one level deep as below:
UPDATE users
SET editoverride = 1
WHERE id IN
(SELECT A.id
FROM
(SELECT users.id
FROM users
JOIN contractorscontractsappliedfor ON contractorscontractsappliedfor.contractorId = users.id
JOIN usertenderstage ON usertenderstage.userId = users.id
WHERE users.live = 1
AND contractorscontractsappliedfor.contractid = 1
AND usertenderstage.stageId = 2
AND usertenderstage.statusid = 6) AS A)
I haven't tested it as don't have MySQL handy.

If else in Mysql Update query

I need a query to update some fields in a table based on count of another field.
Update
bank_sample_map
LEFT JOIN
sample_details ON bank_sample_map.sample_track_id = sample_details.sampletrack_id
LEFT JOIN
order_details ON order_details.sample_detail_id = sample_details.sample_id
LEFT JOIN
test_details ON test_details.test_detail_id = order_details.test_detail_id
SET
bank_sample_map.sample_id = sample_details.sample_id, bank_sample_map.order_id = order_details.order_number,
bank_sample_map.testid = test_details.test_id,bank_sample_map.test_cost = test_details.test_cost
WHERE
bank_sample_map.sample_id IS NULL
AND bank_sample_map.order_id IS NULL
AND bank_sample_map.testid IS NULL
AND (select count(order_number) < 2 from order_details where sample_detail_id = sample_details.sample_id);
If(count(order_number) < 2) I need to update sample_id,order_id,testid,test_cost
Else update sample_id only.
How to change my query to satisfy this condition.

using joins together with aggregates, and retrieving rows when no aggregate exists

The following query on my MySQL tables returns rows from the purchaseorder table that have corresponding entries in the deliveryorder table. How do I construct this query so that I get rows from the purchaseorder table even if no corresponding rows exist in the deliveryorder table? If the users want to see sql table CREATE statements, I can post those, but I'm not posting now as it really makes the question too big.
SELECT
`purchaseorder`.`id` AS `po_id`,
`purchaseorder`.`order_quantity` AS `po_order_quantity`,
`purchaseorder`.`applicable_approved_unit_rate` AS `po_unit_rate`,
`purchaseorder`.`applicable_sales_tax_rate` AS `po_tax_rate`,
`purchaseorder`.`order_date` AS `po_order_date`,
`purchaseorder`.`remarks` AS `po_remarks`,
`purchaseorder`.`is_open` AS `po_is_open`,
`purchaseorder`.`is_active` AS `po_is_active`,
`purchaseorder`.`approved_rate_id` AS `po_app_rate_id`,
`supplier`.`name` AS `sup_name`,
SUM(`deliveryorder`.`quantity`) AS `total_ordered`
FROM `purchaseorder`
LEFT JOIN `deliveryorder` ON (`deliveryorder`.`purchase_order_id` = `purchaseorder`.`id`)
INNER JOIN `approvedrate` ON (`purchaseorder`.`approved_rate_id` = `approvedrate`.`id`)
INNER JOIN `supplier` ON (`approvedrate`.`supplier_id` = `supplier`.`id`)
WHERE (
`purchaseorder`.`is_active` = 1
AND `purchaseorder`.`is_open` = 1
AND `deliveryorder`.`is_active` = 1
AND `approvedrate`.`material_id` = 2
)
HAVING `purchaseorder`.`order_quantity` >= `total_ordered` + 1
You have an aggregating function but no GROUP BY clause, which is wierd, but anyway - something like this? Oops - edited...
SELECT po.id po_id
, po.order_quantity po_order_quantity
, po.applicable_approved_unit_rate po_unit_rate
, po.applicable_sales_tax_rate po_tax_rate
, po.order_date po_order_date
, po.remarks po_remarks
, po.is_open po_is_open
, po.is_active po_is_active
, po.approved_rate_id po_app_rate_id
, s.name sup_name
, SUM(do.quantity) total_ordered
FROM purchaseorder po
LEFT
JOIN deliveryorder do
ON do.purchase_order_id = po.
AND do.is_active = 1
LEFT
JOIN approvedrate ar
ON ar.id = po.approved_rate_id
AND ar.material_id = 2
LEFT
JOIN supplier s
ON s.id = ar.supplier_id
WHERE po.is_active = 1
AND po.is_open = 1
HAVING po.order_quantity >= total_ordered + 1
I couldn't work out how to get the desired results all in one query, but ended up using the following two queries to fulfill my requirements: -
1st query
SELECT
pot.`id` AS `po_id`,
pot.`order_quantity` AS `po_order_quantity`,
pot.`applicable_approved_unit_rate` AS `po_unit_rate`,
pot.`applicable_sales_tax_rate` AS `po_tax_rate`,
pot.`is_open` AS `po_is_open`,
pot.`is_active` AS `po_is_active`,
st.`id` AS `sup_id`,
st.`name` AS `sup_name`,
SUM(dot.`quantity`) AS `total_ordered`
FROM `purchaseorder` pot
INNER JOIN `deliveryorder` dot ON (dot.`purchase_order_id` = pot.`id`)
INNER JOIN `approvedrate` art ON (pot.`approved_rate_id` = art.`id`)
INNER JOIN `supplier` st ON (art.`supplier_id` = st.`id`)
WHERE (
pot.`is_active` = 1
AND pot.`is_open` = 1
AND art.`material_id` = #materialid
AND art.`in_effect` = 1
AND art.`is_active` = 1
AND dot.`is_active` = 1
AND st.`is_active` = 1
)
HAVING pot.`order_quantity` >= `total_ordered` + #materialquantity
2nd query
SELECT
pot.`id` AS `po_id`,
pot.`order_quantity` AS `po_order_quantity`,
pot.`applicable_approved_unit_rate` AS `po_unit_rate`,
pot.`applicable_sales_tax_rate` AS `po_tax_rate`,
pot.`is_open` AS `po_is_open`,
pot.`is_active` AS `po_is_active`,
st.`id` AS `sup_id`,
st.`name` AS `sup_name`,
0 AS `total_ordered`
FROM `purchaseorder` pot
INNER JOIN `approvedrate` art ON (pot.`approved_rate_id` = art.`id`)
INNER JOIN `supplier` st ON (art.`supplier_id` = st.`id`)
WHERE (
pot.`is_active` = 1
AND pot.`is_open` = 1
AND art.`material_id` = #materialid
AND art.`in_effect` = 1
AND art.`is_active` = 1
AND st.`is_active` = 1
AND pot.`order_quantity` >= #materialquantity
AND pot.`id` NOT IN
(
SELECT dot.`purchase_order_id`
FROM `deliveryorder` dot
WHERE dot.is_active = 1
)
)

Mysql::Error: Subquery returns more than 1 row:

In my rails app, I am running a sql query using find_by_sql() since I need subqueries.
This works if I do either the first or second query but when I add them together with the AND, it starts complaining about more than 1 row in subquery.
I want all rows (records) returned that match the criteria. What needs to be fixed/changes here? What is telling mysql I only want 1 row?
Here is the resultant SQL as viewed in the rails log:
Mysql::Error: Subquery returns more than 1 row: select p.* from policies p
where exists (select 0 from status_changes sc join statuses s on sc.status_id = s.id
where sc.policy_id = p.id
and s.status_category_id = '1'
and sc.created_at between '2009-03-10' and '2009-03-12')
or exists
(select 0 from status_changes sc join statuses s on sc.status_id = s.id
where sc.created_at in
(select max(sc2.created_at)
from status_changes sc2
where sc2.policy_id = p.id
and sc2.created_at < '2009-03-10')
and s.status_category_id = '1'
and sc.policy_id = p.id)
AND (select 0 from status_changes sc
where sc.policy_id = p.id
and sc.status_id = 7
and sc.created_at between '2008-12-31' and '2009-03-12')
or exists
(select 0 from status_changes sc
where sc.created_at in
(select max(sc2.created_at)
from status_changes sc2
where sc2.policy_id = p.id
and sc2.created_at < '2008-12-31')
and sc.status_id = 7
and sc.policy_id = p.id)
This line:
AND (select 0 from status_changes sc
Shouldn't it be
AND exists (select 0 from status_changes sc
Subqueries that return more than 1 row are not supported by any SQL server, as far as I am aware.