Convert a SELECT statement into its corresponding UPDATE statement - mysql

I have a SQL query that counts the exact population whose information I need to update using an UPDATE statement. But it contains some complex joins and I'm not sure how to recreate that statement in an UPDATE statement. Any help?
My query is here:
select distinct c.id
from implementation.tt_ngma_exclude_emails nee
join customer c on nee.util_account_id = c.util_internal_id
join customer_notification_contact cnc on cnc.customer_id = c.id
left join customer_notification_contact_audit cnca on cnca.customer_id = c.id
where cnc.changed_on = '2015-11-15 12:30:02';
The goal here is to update a specific field in the customer_notification_contact table, not the implementation table I selected from. I want to set the email field in the cnc table to NULL everywhere that cnc.customer_id = c.id
Here's my attempt but it doesn't seem to work:
UPDATE customer_notification_contact cnc
(select distinct cnc.customer_id opower_customer_id
from implementation.tt_ngma_exclude_emails nee
join customer c on nee.util_account_id = c.util_internal_id
join customer_notification_contact cnc on cnc.customer_id = c.id
where cnc.changed_on = '2015-11-15 12:30:02'
) T2
SET cnc.email = NULL
WHERE cnc.customer_id = T2.opower_customer_id;

please give this a try just replace T1.SOME_COLUMN (2nd last line) with your actual column name that you want to update. I added GROUP BY CNC.CUSTOMER_ID because when you're updating multiple rows you should know which customer the count belongs to. unless you're trying to update all rows with the same count which i am assuming you're not trying to do.
UPDATE customer_notification_contact T1,
(
select count(distinct c.id) AS MY_COUNT,CNC.CUSTOMER_ID
from implementation.tt_ngma_exclude_emails nee
join customer c on nee.util_account_id = c.util_internal_id
join customer_notification_contact cnc on cnc.customer_id = c.id
left join customer_notification_contact_audit cnca on cnca.customer_id = c.id
where cnc.changed_on = '2015-11-15 12:30:02'
GROUP BY CNC.CUSTOMER_ID
)T2
SET T1.SOME_COLUMN = T2.MY_COUNT
WHERE T1.CUSTOMER_ID = T2.CUSTOMER_ID
UPDATE after seeing updated question this should be the query.
UPDATE customer_notification_contact T1,
(
select distinct c.id
from implementation.tt_ngma_exclude_emails nee
join customer c on nee.util_account_id = c.util_internal_id
join customer_notification_contact cnc on cnc.customer_id = c.id
left join customer_notification_contact_audit cnca on cnca.customer_id = c.id
where cnc.changed_on = '2015-11-15 12:30:02'
)T2
SET T1.EMAIL = NULL
WHERE T1.CUSTOMER_ID = T2.id

Related

error 1175 when updating table by another table - WHERE clause exists

I'm trying to update a table using another table, like so, but I get error 1175 saying I don't have a WHERE clause when I do.
update t1 c, t2 dk
set c.date = dk.defaultdate, c.filter = 'word'
where c.id = dk.id and c.name = dk.name and c.color = dk.color and c.country = dk.country
and c.id is not null and c.date is null and c.name is not null and c.color is not null and c.country is not null;
how can I make the needed change anyway?
(im on MariaDB)
The first thing I would suggest here is to rewrite your update query using a proper explicit join:
UPDATE t1 c
INNER JOIN t2 dk
ON c.id = dk.id AND c.name = dk.name AND c.color = dk.color AND
c.country = dk.country
SET c.date = dk.defaultdate,
c.filter = 'word'
WHERE c.id IS NOT NULL AND c.date IS NULL AND c.name IS NOT NULL AND
c.color IS NOT NULL AND c.country IS NOT NULL;

Cant update and select in single query in mysql

UPDATE sub_categories
set creatives_count =
( SELECT COUNT(services.sub_category_id)
from sub_categories
left
join services
on (sub_categories.id = services.sub_category_id)
GROUP
BY sub_categories.id);
BlockquoteError: Table 'sub_categories' is specified twice, both as a target for 'UPDATE' and as a separate source for data.
How can I update my column with the result I obtained in subquery.
You can try below -
UPDATE sub_categories s
join
(
SELECT COUNT(services.sub_category_id) as cnt from sub_categories
left join services on sub_categories.id = services.sub_category_id
GROUP BY sub_categories.id
)A on s.id=A.id
set creatives_count = a.cnt
You could use inner join on the subquery
UPDATE sub_categories
INNER JOIN (
SELECT sub_categories.id my_id, COUNT(services.sub_category_id) my_count
FROM sub_categories
LEFT JOIN services ON sub_categories.id = services.sub_category_id
GROUP BY sub_categories.id) t ON t.my_id = sub_categories.id
SET creatives_count = t.my_count

mysql update query with inner join

I have two tables customer and order. I want to update different values in both tables with one query. For example customer table has a city column and value is germany and order table has status column and value is hold, I want to change germany to london and hold to resolved with one query. Here is the query below
UPDATE customer,order INNER JOIN order ON customer.cust_id = order.cust_id SET cust_city = 'Lahore' AND order_status= 'Resolved' WHERE cust_id = 2
mysql is showing error for this query
MySQL supports this operation:
UPDATE customer c INNER JOIN
order o
ON c.cust_id = o.cust_id
SET c.cust_city = 'Lahore',
o.order_status = 'Resolved'
WHERE c.cust_id = 2 ;
Note: order is a really bad name for a table, because it is a SQL keyword. Choose names for things that do not need to be escaped.
It is very simple to update using a join query in SQL.You can even join two or more tables. Here is an example :
UPDATE customer_table c
INNER JOIN
employee_table e
ON c.city_id = e.city_id
INNER JOIN
anyother_ table a
ON a.someID = e.someID
SET c.active = "Yes"
WHERE c.city = "New york";

Update Query with Correlated Subquery

I'm trying to convert a Foxpro application into .NET. As part of that conversion I'm converting the data from DBF tables to Sql server.
I need to come up with a couple new fields in the Customer table based on the Orders table, FirstOrder and LastOrder.
I just can't seem to muddle through how to do this in TSql. I know how I'd do it in Foxpro, and I could actually still do it there if I had to, but I know I need to learn how to do this in Sql.
Here is the basic structure.
Customer Table has an Id, then the FirstOrder and LastOrder fields I need updated.
Order Table has OrderDate, but here is the real curve. The Customer Id can exist in 5 different fields inside the Order: ShipperId, PickupId, ConsigneeId, DeliveryId, or BillingId.
So something like:
UPDATE customers
SET FirstOrderDate =
(Select MIN(OrderDate)
FROM Orders o
WHERE o.ShipperId = Customers.Id or
o.PickupId = Customers.Id or
o.ConsigneeId = Customers.Id or
o.DeliveryId = Customers.Id or
o.BillingId = Customers.Id)
Just can't seem to find out how to tie the subquery with the main update query.
Thanks,
-Sid
EDIT:
Here's the SELECT that's working based on MarkD's suggestion:
Select C.Id,Min(o.OrderDate) as firstorder, MAX(o.OrderDate) as lastorder
from Customers C
JOIN Orders o
on o.ShipperId = C.Id or
o.PickupId = C.Id or
o.ConsigneeId = C.Id or
o.DeliveryId = C.Id or
o.BillingId = C.Id
GROUP BY C.Id
So now do I use this as a subquery or cursor to post back to the Customers table?
Although I think the JOIN criteria is highly unlikely, it looks like you're trying to do this?
EDIT: I've modified the JOIN criteria but this is what you're after.
Grouping By columns that are OR'd is odd.
;WITH MinOrderDates AS
(
SELECT CustID
,OrderDate = MIN(OrderDate)
FROM Orders
GROUP BY CustID
)
UPDATE C
SET FirstOrderDate = MIN(O.OrderDate)
FROM Customers C
JOIN MinOrderDates O ON C.Id = O.CustID
This is what your query would look like with the ORs
;WITH MinOrderDates AS
(
SELECT ShipperId
,PickupId
,ConsigneeId
,DeliveryId
.BillingId
,OrderDate = MIN(OrderDate)
FROM Orders
GROUP BY ShipperId
,PickupId
,ConsigneeId
,DeliveryId
.BillingId
)
UPDATE C
SET FirstOrderDate = MIN(O.OrderDate)
FROM Customers C
JOIN MinOrderDates O ON o.ShipperId = C.Id or
o.PickupId = C.Id or
o.ConsigneeId = C.Id or
o.DeliveryId = C.Id or
o.BillingId = C.Id
EDIT: Though I am having a hard time finding fault with your posted syntax.
Try this
UPDATE customers
SET FirstOrderDate =
(Select MIN(OrderDate)
FROM Orders
WHERE ShipperId = Customers.Id or
PickupId = Customers.Id or
ConsigneeId = Customers.Id or
DeliveryId = Customers.Id or
BillingId = Customers.Id)

MySQL GROUP BY performance issue

This is the query I'm performing (without some Joins that are not relevant):
SELECT a.*, c.id
FROM a
LEFT OUTER JOIN b ON a.id = b.id_anunciante
LEFT OUTER JOIN c ON c.id = b.id_rubro
GROUP BY a.id
Each row of "a" is linked with 1 to 5 rows in "b".
The problem is that GROUP BY has performance issues (it takes 10x or more using GROUP BY than not using it). I need to retrieve only one row of each member in "a".
How can I make this faster?
edit: I need to be able to filter by a.id AND/OR c.id. The resultset I should be getting is only 1 row per "valid" member of "a", meaning the rows that match the constraints. Rows that don't match the filters shouldn't be returned.
In my original query, this would be done this way:
SELECT a.*, c.id
FROM a
LEFT OUTER JOIN b ON a.id = b.id_anunciante
LEFT OUTER JOIN c ON c.id = b.id_rubro
WHERE c.id = 1
OR a.id = 1
GROUP BY a.id
a.id, b.id_anunciante, b.id_rubro, c.id are all indexes.
SELECT a.*,
(
SELECT c.id
FROM b
JOIN с
ON c.id = b.id_rubro
WHERE b.id_anunciante = a.id
-- add the ORDER BY condition to define which row will be selected.
LIMIT 1
)
FROM a
Create the index on b (id_anunciante) for this to work faster.
Update:
You don't need the OUTER JOINs here.
Rewrite your query as this:
SELECT a.*, c.id
FROM a
JOIN b
ON b.id_anunciante = a.id
JOIN c
ON c.id = b.id_rubro
WHERE a.id = 1
UNION ALL
SELECT a.*, 1
FROM a
WHERE EXISTS
(
SELECT NULL
FROM c
JOIN b
ON b.id_rubro = c.id
WHERE c.id = 1
AND b.id_anunciante = a.id
)
Add ORDER BY NULL to avoid the implicit sorting MySQL does when doing a group by.
I suppose you have indexes/PKs on a.id, b.id_anunciante, b.id_rubro and c.id ? I guess you could try adding a composite index on (b.id_anunciante, b.id_rubro) if your mysql version is not able to do an index merge.