Problems with updating column from another table in postgresql - sql

My db is postgresql. I have 4 tables and need to copy id of "payment_option" record to column in "settlement" table.
Quick info about model:
Account has N invoices, Invoice has N settlements. Settlement has one of four payment options that are currently determined by column with string (PAYPAL, STRIPE, LEGACY, WIREPAYMENT). Account has N payment_options (always 4 in current state. Each type once) and each of these payment options has again one of those types in a column as string (PAYPAL, STRIPE, LEGACY, WIREPAYMENT). I need to add fkey pointing from settlement table to payment_option table that I can find settlement->invoice->account->payment_option
For this I need to do multiple join and do something like "UPDATE JOIN" but I am failing for some reason. My statement updates all settlement.payment_option_id on id of the first payment_option but not on id of payment_option bound through the account and invoice tables.
update settlement
set payment_option_id = P.id
from payment_option as P
inner join invoice as I on P.account_id = I.account_id
inner join settlement as S on S.invoice_id = I.id
where S.payment_option_type = P.type;
How to write it correctly and what is wrong? I think issue is in "SET" becuse when I write select with following joins it works as expected
Thanks Lukas

It seems strange that you are repeating the the reference to settlement in the FROM clause. Perhaps you intend:
update settlement s
set payment_option_id = P.id
from payment_option P join
invoice I
on P.account_id = I.account_id
where S.payment_option_type = P.type and S.invoice_id = I.id

Related

Retrieve data from multiple tables returning null and not null values

I'm trying to create a query which needs to retrieve the latest prices for thousands of items; the thing is, I need two separate columns from two tables, to return null or not null values.
These two tables contain prices which are different from one another.
If I don't have a price in column A from table 1, it should return null, and column B from table 2 would return a value (if there's data).
I'm leaving below the latest "version" of the query I tried to run but again, to no avail; the data is incorrect, it returns the wrong prices.
SELECT a.orderid,
a.itemid,
d.currency,
d.itemcategory,
a.originalprice,
c.companyid,
b.price1,
e.price2,
Max(b.date) AS date,
c.companycategory
FROM orders AS a
INNER JOIN companydata AS b
ON a.itemid = b.itemid
INNER JOIN companycodes AS c
ON a.orderid = c.orderid
INNER JOIN orderoverview AS d
ON a.orderid = d.orderid
INNER JOIN pricingdata AS e
ON a.sku = e.sku
WHERE a.orderid = '123456'
GROUP BY a.orderid,
a.itemid,
d.currency,
d.itemcategory,
a.originalprice,
c.companyid,
b.price1,
e.price2,
c.companycategory
It doesn't even return the latest pricing data for an item.
I am not sure if I should've used different types of joins but I spent the entire day googling and trying stuff.
The tables containing the prices are pricingdata (e) and companydata (b); if there are no prices for the companies the orders were created, they should return null values.
So far this query returned horrific results, and I tried using CASE but it won't work for checking multiple items at once; I will search for these prices by the orderid which may contain thousands of items.
Temps were my first attempt then I started questioning if I really need them so I gave up.
I also tried using while loops but...failed miserably x2.
I read about cursors but I don't think they apply here.
If it wasn't obvious by my first world problems, I'm a beginner.
Any help is highly appreciated and I thank you all in advance!
L.E. tried Dale's K advice and managed to enter the data here SQL Fidler test
By "incorrect prices" I mean it ignores the max(date) and somehow brings prices from other items/companies.
The output should bring the latest price per item, company and supplier. If there's data missing for the company/supplier, the cell should be populated with NULL.
Thank you once more!

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

Excel SQL update based on values in 2 tables

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

SQL Query with 4 Tables but showing multiple rows

Apologies for my basic question, my minds gone blank and for some reason I can't think for the life of me what I've done.
Ok, so I have four tables
dbo.loanunits (this contains all loan units including status of in or out and loanid)
dbo.loanunits2 (this contains extra info on loan units including customer id and loanid)
dbo.loantrans (this contains transactions of loanunits, i.e. history of statuses in's and outs. also includes loanid of item sent out)
dbo.customers (this contains customer id and customer name)
This is my script:
SELECT
dbo.loanunits.loan_id, dbo.loanunits.loan_name,
dbo._loanunits.loan_status, dbo.customers.customername
FROM
dbo.loanunits
INNER JOIN
dbo.loantrans ON dbo.loanunits.loan_id = dbo.loantrans.loan_tranunitid
INNER JOIN
dbo.loanunits2 ON dbo.loantrans.loan_id = dbo.loanunits2.loan_id
INNER JOIN
dbo.customers ON dbo.loanunits2.customer_account_code = dbo.customers.customer_account_code
WHERE
(dbo.loanunits.loan_status = 'out')
I am currently getting the number of results in the transactions table but I should be getting only unique values in the loan units as I only want to see loan units out with customers and who they are with.
I do not see any use of loantrans table, so you may remove it.
SELECT
dbo.loanunits.loan_id, dbo.loanunits.loan_name,
dbo._loanunits.loan_status, dbo.customers.customername
FROM
dbo.loanunits
/*INNER JOIN
dbo.loantrans ON dbo.loanunits.loan_id = dbo.loantrans.loan_tranunitid */
INNER JOIN
/* dbo.loanunits2 ON dbo.loantrans.loan_id = dbo.loanunits2.loan_id */
dbo.loanunits2 ON dbo.loanunits.loan_id = dbo.loanunits2.loan_id
INNER JOIN
dbo.customers ON dbo.loanunits2.customer_account_code = dbo.customers.customer_account_code
WHERE
(dbo.loanunits.loan_status = 'out')
Also, you could easily use the DISTINCT keyword.

SQL Query Add to total sum if.. else dont add

How Do I achieve this result ? What I need is calculate total cost of a Product when a product is made up of components. New for me, I should add a 100$ to total cost if customer chooses for a service called Delivery.
This is what I have tried so far.
Select Sum(Component.Cost*ProductComponent.Quantity) as TotCost from ProductComponent Left Join Component on ProductComponent.ComponentId = Component.ComponentId
I Guess this will get me total cost of a product.
Now There is another table Service which has a many to many relationship with Order. Order has a many to many relationship with Service. What I need is I need to add another 100$ in total cost if there is 'deliverly' used in service.
I have attached an ER diagram of my database structure. I hope my question is clear.
The basic idea is that you'd have to put a case statement in there to add the $100 if there is a record in the Service table for a given order. The below query should get you most of the way there, but looking at the cardinality of your relationships you may need to group the results or use subqueries to chop it down to one row.
SELECT CASE WHEN sa.ServiceID IS NOT NULL THEN SUM(Component.Cost*ProductComponent.Quantity) + 100
ELSE SUM(Component.Cost*ProductComponent.Quantity) END AS TotCost
FROM ProductComponent pc
LEFT JOIN Component on ProductComponent.ComponentId = Component.ComponentId
JOIN OrderLine o ON o.ProductID = pc.ProductID
JOIN StaffAssignment sa ON sa.SaleID = o.SaleID
It looks like multiple StaffAssignments could give Service for one order so that's where you might want to use a subquery like SELECT Top 1 ServiceID FROM StaffAssignment WHERE SaleID = o.SaleID AND ServiceID IS NOT NULL
I don't have time to test this at the moment but hopefully it gives you some ideas to get this solved.
You can see the service as another product and add it to the ones already there with a UNION
SELECT TotCost = SUM(LineCost)
FROM (SELECT c.Cost * pc.Quantity as LineCost
FROM OrderLine ol
INNER JOIN ProductComponent p ON ol.ProductID = pc.ProductID
LEFT JOIN Component c on pc.ComponentId = c.ComponentId
Where ol.SaleID = #ID
UNION ALL
SELECT 100
FROM StaffAssignment sa
INNER JOIN Service s ON sa.ServiceID = s.ServiceID
Where Name = 'Delivery'
And sa.SaleID = #ID) a
Adding a field to the Services table would be useful, if the services have a flat values, to avoid to have magic constants in your code/queries