Excel SQL update based on values in 2 tables - sql

Let me start by saying that I am not using the right tools for the job but they are the only tools I have access to.
I am using Excel as a database that contains multiple tables with associated data. Normally in a database, this data could be associated with a foreign key I believe however that is not the case with Excel.
I have 2 tables:
TABLE items
batch_id customer_id
1 1
2 1
3 2
and
TABLE customers
id customer
1 cust1
2 cust2
I have a userform which only allows the user to select a customer by name.
What I would like to be able to do is update the customer_id in the items table based on a specific batch_id and a customer name.
This is what I have so far that isn't working.
UPDATE [items$]
SET [items$].customer_id=[customers$].id
INNER JOIN [customers$]
ON [items$].customer_id=[customers$].id
WHERE [items$].batch_id='value1'
AND [customers$].customer='value2'
[UPDATE]
The following seems to be a little closer to answer but is giving me a 'Operation must use an updateable query.' error.
UPDATE items
SET items.customer_id=(
SELECT FIRST(customers.id)
FROM customers
WHERE customers.customer=value2)
WHERE items.batch_id=value1;
I keep getting a 'Operation must use an updateable query error' with this but otherwise I see no reason why it shouldn't work

I'm not sure how to put in excel VBA. But the update syntax should be like (if u want to update all the rows)
Update items
set items.customer_id = (select customers.id
from customers inner join items
on customers.id = items.customer_id
where customers.id='Value2'
and items.batch_id='Value1');
Hope this might help u

Try with the following once may be you will get your expected result.
But this is the case of SQL.
UPDATE items i
JOIN customers c ON i.customer_id = c.id
SET i.customer_id = c.customer

Related

How to use not in / not like to compare values from different tables in SQL

I have SQL 2019 with these two tables - Orders and Customers with respective columns
id,order_comment,customer_id
in Orders and
id,customer_name
in Customers. Order_comment is ntext type.
I need to update the order_comment with customer_name value.
The update should be something like this:
update o set order_comment=concat(c.customer_name,';',o.order_comment)
from
orders o
left join customer c on c.id=o.customer_id
where o.id=1 and
convert(varchar(255),order_comment) not in
(select b.customer_name from customer b where o.customer_id=b.id)
If the customer_name is already part of the order_comment then the update should not happen.
The above query works ok when the order_comment is empty. But if there is already text in the comment, it keeps updating the value. How should i change the query so when there is already text in the comment section, the update to happen only once?
There a lot of ways to achieve your goal and of course the best way depends on your setup and your further goals.
In order to keep your update statement as most similar as possible to your attempt, you could do this:
UPDATE o SET order_comment=CONCAT(c.customer_name,';',o.order_comment)
FROM
orders o
LEFT JOIN customers c ON c.id=o.customer_id
WHERE o.order_comment IS NULL OR o.order_comment NOT LIKE CONCAT(c.customer_name,'%');
There are also other possibilites like subselects, not exists etc., the best idea is that you try what is the best for you. You can check this example here:
fiddle

Updating table and setting the field values to the result of a left join

I have a table Sales with the field Vendor ("Company A", "Company B", "Trader X"), and I have made a separate table called Vendors with two fields: VendorID and VendorName.
I want to delete the Vendor field in the table Sales and replace it with a VendorID field and fill the fill the field with the corresponding VendorIDs. In other words replace the names of the vendors in the Sales table with their ID from the Vendors table.
I have tried numerous solutions but they do not work. Here is one that I think will work. Some entries in the Sales table do not have any Vendors listed. There are 203 entries and the left join, when run on its own, returns all 203 vendors and the appropriate null values.
Update Sales
Set Sales.VendorID = (Select VendorID From Vendors v Left Join Sales s on
v.VendorName = s.Vendor);
When I run this I get a dialog box asking :
Enter Parameter Value
Or I get the error message :
Operation must use an updateable query
I am using MS Access 2016.
I think that you don't need a subquery, you could just use the UPDATE ... JOIN ... SET syntax, like :
UPDATE sales AS s
INNER JOIN Vendors AS v ON v.VendorName = s.Vendor
SET s.VendorID = v.VendorID

Scalar subquery contains more than one row

Im working with H2 database and wanted to move some data. For that I created the following Query:
UPDATE CUSTOMER
SET EMAIL = SELECT service.EMAIL
FROM CUSTOMER_SERVICE AS service
INNER JOIN CUSTOMER AS customer ON service.ID = customer.CUSTOMER_SERVICE_ID;
When I now perform it in the H2 console I get the following error:
Scalar subquery contains more than one row; SQL statement:
UPDATE CUSTOMER
SET EMAIL = SELECT service.EMAIL
FROM CUSTOMER_SERVICE AS service
INNER JOIN CUSTOMER AS customer ON service.ID = customer.CUSTOMER_SERVICE_ID [90053-192] 90053/90053 (Hilfe)
What is this error telling me?
EDIT
What I want to achiev with my query:
Actually every CUSTOMER has a CUSTOMER_SERVICE. And I simply want to move the COLUMN EMAIL from CUSTOMER_SERVICE to the CUSTOMER Table. for that I already added a email column to the user. I hoped to be able to do it with my query but obviously not.
Your query is not syntactically valid (all subqueries must have parentheses around them).
What you are missing is a correlation clause. I believe you want:
UPDATE CUSTOMER c
SET EMAIL = (SELECT cs.EMAIL
FROM CUSTOMER_SERVICE s
WHERE s.ID = c.CUSTOMER_SERVICE_ID
);
I don't know what this is supposed to be: [90053-192] 90053/90053 (Hilfe).
Your select query is returning more than one row. If you don't want it to, then you need to do something like an aggregate or LIMIT 1 or something similar.
Your sub-query for at least one of your customers has multiple email addresses.
You could ... (Select top 1 serverice.email ...
Or ... (Select max(serverice.email) ...
Update Customer Set EMail=B.Email
From Customer A
Join (Select ID,max(EMail) as EMail From CUSTOMER_SERVICE Group By ID) B
on (A.CUSTOMER_SERVICE_ID = B.ID)
I've spend a lot time with this error type (there shoudn't be duplicates in DB).
At last I've found problem via SQL with COUNT like this:
UPDATE CUSTOMER
SET EMAIL = SELECT COUNT(service.EMAIL)
FROM CUSTOMER_SERVICE AS service
INNER JOIN CUSTOMER AS customer ON service.ID =
customer.CUSTOMER_SERVICE_ID;
And then select problem rows with EMAIL!='1'

SQL multiple joins error

I am trying to create a temporary table with information from the orders table in. I then want to join stock.name, and most of the supplier information using the supplier ID which is the foreign key in the orders table. This is my code below, but I seem to get an error in access.
This query will be run in VB to create a temporary table to pass over data to excel. The table should only store one record but should be deleted soon after excel takes the data from it. Thanks in advance to anyone that can help me.
SELECT orders.purchase_order_number, orders.part_number, stock.name, orders.quantity, orders.order_date, suppliers.last_name, suppliers.first_name, suppliers.address_1, suppliers.address_2, suppliers.city, suppliers.postcode
INTO order_temp FROM orders
INNER JOIN suppliers ON orders.supplier_ID = suppliers.supplier_ID
INNER JOIN stock ON orders.part_number = stock.part_number
WHERE orders.purchase_order_number = 'PO10367' and suppliers.supplier_ID = 20
If you are querying from VB (such as VB.net), then when you query to your LOCAL VB app from the connection, you do not need to select into table... The error you are probably getting is that the table already exists and can't recreate it, it must be dropped... But if you just query to VB app, and no table created, you should be good to go.

Select based on the number of appearances of an id in another table

I have a table B with cids and cities. I also have a table C that has these cids with extra information. I want to list all the cids in table C that are associated with ALL appearances of a given city in Table B.
My current solution relies on counting the number of times the given city appears in Table B and selecting only the cids that appear that many times. I don't know all the SQL syntax yet, but is there a way to select for this kind of pattern?
My current solution:
SELECT Agents.aid
FROM Agents, Customers, Orders
WHERE (Customers.city='Duluth')
AND (Agents.aid = Orders.aid)
AND (Customers.cid = Orders.cid)
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
It only works because I know right now with the HAVING statement.
Thanks for the help. I wasn't sure how to google this problem, since it's pretty specific.
EDIT: I'm pinpointing my problem a bit. I need to know how to determine if EVERY row in a table has a certain value for a field. Declaring a variable and counting the rows in a sub-selection and filtering out my results by IDs that appear that many times works, but It's really ugly.
There HAS to be a way to do this without explicitly count()ing rows. I hope.
Not an answer to your question, but a general improvement.
I'd recommend using JOIN syntax to join your tables together.
This would change your query to be:
SELECT Agents.aid
FROM Agents
INNER JOIN Orders
ON Agents.aid = Orders.aid
INNER JOIN Customers
ON Customers.cid = Orders.cid
WHERE Customers.city='Duluth'
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
What variant of SQL are you using?
To start with, you can (and should) use JOIN instead of doing it in the WHERE clause, e.g.,
select Agents.aid
from Agents
join Orders on Agents.aid = Orders.aid
join Customers on Customers.cid = Orders.cid
where Customers.city = 'Duluth'
group by Agents.aid
having count(Agents.aid) > 1
After that, I'm afraid I might be a little lost. Using the table names in your example query, what (in English, not pseudocode) are you trying to retrieve? For example, I think your sample query is retrieving the PK for all Agents that have been involved in at least 2 Orders involving Customers in Duluth.
Also, some table definitions for Agents, Orders, and Customers might help (then again, they might be irrelevant).
I'm not sure if I understood you problem, but I think the following query is what you want:
SELECT *
FROM customers b
INNER JOIN orders c USING (cid)
WHERE b.city = 'Duluth'
AND NOT EXISTS (SELECT 1
FROM customers b2
WHERE b2.city = b.city
AND b2.cid <> cid);
Probably you will need some indexes on these columns.