mysql update query with inner join - mysql

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";

Related

Nested SQL query?

I have 2 tables like this:
product_table[ product_id, product_name,original_store_id, destination_store id]
and
store_table[ store_id, establishment_date, location]
What I want to find is: From all those products that are shipped TO stores with no establishment date, how many of them are shipped FROM stores with establishment date?
This is my query:
SELECT count(a.product_id) as count_of_products
FROM product_table a
JOIN store_table b
ON a.original_store_id = b.store_id AND a.destination_store_id = b.store_id
WHERE b.establishment_date IS NULL
I understand this should be a nested query, but how do I put them here?
You may try adding a second join to the store_table table to further restrict to only products shipped from stores with an establishment date:
SELECT COUNT(a.product_id) AS count_of_products
FROM product_table a
INNER JOIN store_table b
ON a.destination_store_id = b.store_id
INNER JOIN store_table c
ON a.original_store_id = c.store_id
WHERE
b.establishment_date IS NULL AND
c.establishment_date IS NOT NULL;

Using column as table join with concat

I've been trying to join another table with the table name matching a value in a column from another table.
If I hard-code the table name to a matching table like __gun it works fine but I cannot get the col value to be used + concat underscores to the beginning.
The problem lies in the left join here:
left join CONCAT('__', b.related_table) c on b.related_id = c.id
I need the related_table column to be used in the join. With __ before it.
Attempts:
SELECT a.*, c.*, b.equipable, b.related_table FROM inventory a
inner join items b on a.item_id = b.id
left join CONCAT('__', b.related_table) c on b.related_id = c.id
WHERE 1=1
and a.id = :inventory_id
and a.user_id = :user_id
SELECT a.*, c.*, b.equipable, b.related_table FROM inventory a
inner join items b on a.item_id = b.id
left join '__'+b.related_table c on b.related_id = c.id
WHERE 1=1
and a.id = :inventory_id
and a.user_id = :user_id
SELECT a.*, c.*, b.equipable, b.related_table FROM inventory a
inner join items b on a.item_id = b.id
left join "__"+Cast(b.related_table as nvarchar(4000)) c on b.related_id = c.id
WHERE 1=1
and a.id = :inventory_id
and a.user_id = :user_id
Thank you for considering my question
You cannot construct a table name.
Plan A: Rethink the schema. It is usually bad design to have multiple 'identical' tables.
Plan B: Write a Stored Procedure that uses CONCAT, PREPARE, EXECUTE, and DEALLOCATE_PREPARE to build and run the query.
You can do this using Prepared Statements or you can say dynamic SQL. Follow these steps :
Use SET for table name.
Use CONCAT to get the desired table name.
PREPARE statement for table created at step 1.
EXECUTE statement.
DEALLOCATE PREPARE to release the prepared statement.

Convert a SELECT statement into its corresponding UPDATE statement

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

MySql crazy join thorugh a grouping table

I have a database structure with the following setup:
po: id, stockNumber, factoryId, other columns
order: id, stockNumber, factoryId, other columns
stock_number: id, stockNumber, groupId
factory: id, name, groupId
The important part here is the stock_number/factory tables. The groupId column is just an integer and if two or more rows in the table have the same value then their stock numbers/factory are considered the same. Typically this is used for different sizes of the same product.
What I'd like to do is write a query that will join "order" to "po" through the group of stock_number and factory so I can find orders with no matching po. Also the factory has to match the same way.
I have this query if I have a specific stock number/factory in mind but I'd like to update it to query the whole orders table for me:
SELECT id
FROM order
WHERE
styleNumber IN (SELECT a.stockNumber FROM stock_number a INNER JOIN stock_number b ON a.groupId = b.groupId or a.id = b.id WHERE b.stockNumber = '123')
AND factoryId IN (SELECT a.submitter_id FROM submitter a INNER JOIN submitter b ON a.groupId = b.groupId OR a.submitter_id = b.submitter_id WHERE b.SUBMITTER_ID = 'alpha');
EDIT: I came up with this query which I think might be on the right track. It only joins in the stock number so it doesn't do factory yet. Can anyone confirm if I'm going in the correct direction:
SELECT *
FROM order o
LEFT JOIN stock_number s_o ON o.stockNumber = s_o.stockNumber
LEFT JOIN stock_number s_p ON s_o.groupId = s_p.groupId
LEFT JOIN po p ON s_p.stockNumber = p.stockNumber
WHERE p.id IS NULL;
Just join all the tables.
select o.id
FROM order AS o
JOIN stock_number AS sn ON sn.stockNumber = o.stockNumber
JOIN submitter AS su ON ON o.factoryId = su.submitter_id
You could use an anti-join pattern. In this example, it looks complicated because of the two relationship tables. But a query something like this:
SELECT o.id
, o.stockNumber
, o.factoryId
FROM `order` o
LEFT
JOIN `stock_number` s
ON s.stockNumber = o.stockNumber
LEFT
JOIN `factory` f
ON f.id = o.factoryId
AND f.groupId = s.groupId
LEFT
JOIN `po` p
ON p.stockNumber = s.stockNumber
AND p.factoryId = f.id
WHERE p.id IS NULL
The anti-join pattern is easier to visualize with a simpler example. Say you had the order table (as in your example), and an order_line table, with rows related to the order table by the order_id column.
order_line: id, order_id, othercolumns
To get order along with matching order_line rows:
SELECT o.id AS order_id
, l.id AS line_id
FROM `order` o
JOIN `order_line` l
ON l.order_id = o.id
To include rows from order that don't have any matching rows in order_line, we can use an outer join. We add the LEFT keyword:
SELECT o.id AS order_id
, l.id AS line_id
FROM `order` o
LEFT
JOIN `order_line` l
ON l.order_id = o.id
That gets all rows from order, including rows that don't have a matching row in order_line. The trick now is to exclude all the rows that have a matching row. For any rows that didn't have a match, the columns from order_line will be NULL. So we can add a test in the WHERE clause, to exclude rows that had a match.
SELECT o.id AS order_id
, l.id AS line_id
FROM `order` o
LEFT
JOIN `order_line` l
ON l.order_id = o.id
WHERE l.order_id IS NULL
That gets us rows from order that don't have a matching row in order_line.
We can use this same pattern in a more complicated query. We use outer join operations, and rows from order that don't have a matching row in po will have NULL values for the columns from po.

Using Select & Insert in the same query

I have three tables and I'm trying to do a SELECT from one and INSERT to the other with using ON on the three columns with the same values.
Here's what I trying...
INSERT INTO
CustomerDetails_TEST
(Region_ID)
SELECT
RegionStatesUS.Region_ID
LEFT JOIN Customers ON Customers.Customer_ID = CustomerDetails_TEST.Customer_ID
LEFT JOIN RegionStatesUS ON RegionStatesUS.RegionState = Customers.BillingStateOrProv
FROM Customers
WHERE Customers.Customer_ID = CustomerDetails_TEST.Customer_ID
The tables are...
CustomerDetails_TEST
RegionStatesUS
Customers
And I'm trying to INSERT the value from RegionStatesUS.Region_ID using the Customer_ID INTO CustomerDetails_TEST.Region_ID
What am I missing here?
Your SQL syntax is wrong, I think you might want this:
INSERT INTO CustomerDetails_TEST (Region_ID)
SELECT r.Region_ID
FROM Customers c1
LEFT JOIN CustomerDetails_TEST c2
ON c1.Customer_ID = c2.Customer_ID
LEFT JOIN RegionStatesUS r
ON c1.BillingStateOrProv = r.RegionState
Update query would be similar to this not tested:
UPDATE CustomerDetails_TEST c1
LEFT JOIN Customers c2
ON c1.Customer_ID = c2.Customer_ID
LEFT JOIN RegionStatesUS r
ON c2.BillingStateOrProv = r.RegionState
SET c1.Region_ID = r.Region_ID
FROM comes before LEFT JOIN. The error message is hinting at that. Try again.
Couldn't see where to comment
just a note on how to update, or
insert into mytable
select from sometable
on duplicate key update
id = sometable.id;