Updating a field within a table based on a field within the same table - sql

HI ALL
I wish to update a row within my table from a row within that same table,
I have a table called INVENTORY. it stores PRICES for products.
I have SALES codes and I have STOCK codes which are related.
I wish to transfer all the PRICING from the SALES codes to the STOCK codes.
I wish to do something like this:
update INVENTORY
set PRICE = (SELECT PRICE WHERE CODE = "SALES CODE EQUIVALENT OF THE STOCK CODE IM IN")
WHERE
CODE = "SOME STOCK CODE"
a SALES CODE would look like this "U_12345", its STOCK code equivalent would look like "S_12345"
thanks

You're very close, you just need to specify which table you're selecting from as part of your sub-query...
update INVENTORY
set PRICE = (SELECT PRICE FROM your_table WHERE CODE = "SALES CODE EQUIVALENT OF THE STOCK CODE IM IN")
WHERE
CODE = "SOME STOCK CODE"
Even if "your_table" is INVENTORY, you still need to specify it in there.
The only time it gets 'tricky' is when your selecting from the same table that you're update, AND when you need a value from the updated record in the SELECT statement. In that case you need to differentiate between the two references, using an alias. For example...
update INVENTORY
set PRICE = (SELECT PRICE FROM INVENTORY AS [new_price] WHERE [new_price].CODE = INVENTORY.NEW_CODE)
WHERE
CODE = "SOME STOCK CODE"

UPDATE INVENTORY
SET PRICE = i_sales.PRICE
FROM INVENTORY, INVENTORY i_sales
WHERE INVENTORY.CODE LIKE 'S\_%'
AND i_sales.CODE = REPLACE(INVENTORY.Code, 'S', 'U')
This updates prices for all 'stock' records in INVENTORY with prices from the corresponding 'sales' records.
If you would prefer to update individual prices, change WHERE to something like this:
WHERE i_stock.CODE = 'S_12345'
or this:
WHERE i_stock.CODE IN ('S_12345', 'S_12346')
Note: The FROM syntax used is based on this doc page.

Related

Access: How to retrieve a certain field from a table and return it?

Background
I am currently working on a simple access database for a small bookstore. The business sells books as well as other items.
See following ER-diagram here
Problem
My problem starts in the table Transaction. I would like to create a simple form where a subtotal is calculated as quantity purchased multiplied by the price (both of a certain item).
However the Price field is either in the BookInfo, FoodAndBev, or ApparelAndSupplies table.
Question
How can I traverse the Transaction table to Items and to one of the tables I listed depending on the StockNum in Transaction?
For example, a customer buys an item with StockNum BK001. I would like to retrieve the Price corresponding to BK001 in the BookInfo table and return to Transaction to be used for calculating the subtotal.
The field StockNum exists in tables BookInfo, FoodAndBev, and ApparelAndSupplies.
Sample Data: BookInfo, Items, Transaction
Ideal Output: Transaction 1: A customer buys 2 copies of a book with StockNum 'BK001' (disregard what I already have in the screenshot). The Price of 'BK001' is $119.99 which I would need to retrieve from BookInfo (my problem is I want to make sure it goes to BookInfo not the other two tables which have StockNum also), so the subtotal would then be calculated and would show $239.98. For now, I've been doing this manually. I want to be able to do this with different StockNum such as those that start with AS for Apparel and Supplies and FB for food and beverage.
Thanks in advance!
Left-Joining all tables and using Case-When-Expression (which is function switch in Access) for different price multiplication:
SELECT t.StockNum, t.NumOrdered,
switch(
Left(t.StockNum,2) = 'BK' , (t.NumOrdered * b.Price),
Left(t.StockNum,2) = 'AS' , (t.NumOrdered * a.Price),
Left(t.StockNum,2) = 'FB' , (t.NumOrdered * f.Price),
) AS subtotal
FROM Transaction t
LEFT JOIN BookInfo b ON b.StockNum = t.SockNum
LEFT JOIN ApparelAndSupplies a ON a.StockNum = t.SockNum
LEFT JOIN FoodAndBev f ON f.StockNum = t.SockNum

Access Query parameter that uses a separate table to eliminate or include records

I have one table, Main, which is the main accounting table with all the transactions. I have a second table, Payments, which i keep track of payments and specifically which invoice a given payment has paid off.
I need a report that will be dynamic and flexible; really my accounting workhorse. The report i need will search between dates, customer Id's, record status, account1, account2, and pay status.
So i have a form built out to handle these inputs, but i am having trouble with "pay status" as in, how to form a parameter with it. My current code,
SELECT Main.Invo, Main.InvoDate, Main.Amt, Main.PartyId, Main.TboInvoRloc, Main.TboDocNo, Main.TboPax
FROM Main
WHERE Main.RecSrce<>"Accounts"
AND Main.InvoDate BETWEEN [Forms]![GeneralReport]![startDate] AND [Forms]![GeneralReport]![endDate]
AND Main.PartyId =IIF([Forms]![GeneralReport]![PartyID] IS NULL, PartyID, [Forms]![GeneralReport]![PartyID])
AND Main.Status = IIF([Forms]![GeneralReport]![Status] IS NULL, Status, [Forms]![GeneralReport]![Status])
AND Main.Ac1 = IIF([Forms]![GeneralReport]![Ac1] IS NULL, Ac1, [Forms]![GeneralReport]![Ac1])
AND Main.Ac2 = IIF([Forms]![GeneralReport]![Ac2] IS NULL, Ac2, [Forms]![GeneralReport]![Ac2])
;
covers everything but the "pay status." I wanted to do something like
If checkbox=true, then include paid items, else exclude items where Main.Invo = Payments.DueInvo
My other thought was to exclude the paid items in the initial query, and then include them in a subsequent union query if the checkbox is checked. Any help or thoughts would be appreciated.
Set unbound checkbox for TripleState Yes. Or use a combobox with 3 options (Paid, Unpaid, All) because users might be confused by a triple state checkbox.
Build an aggregate query on Payments table that totals the payments by invoice. Join that query to Main (this assumes invoice is unique in Main).
Calculate a field and set a parameter under that field.
If using checkbox:
IsNotPaid: Amt <> Nz(SumOfPayments,0)
LIKE Forms![GeneralReport]!checkboxname & "*"
If using combobox:
PaidStatus: IIf(Amt = Nz(SumOfPayments,0), "Paid", "Unpaid")
LIKE IIf(Forms![GeneralReport]!comboboxname = "All", "*", Forms![GeneralReport]!comboboxname)
An alternative to aggregate query is DSum() domain aggregate function but that will probably perform slower.
Consider setting payment detail columns to NULL depending on checkbox. Specifically, join the Payments table and run a logical condition on fields in SELECT assigning NULL or not.
SELECT m.Invo, m.InvoDate, m.Amt,
m.PartyId, m.TboInvoRloc,
m.TboDocNo, m.TboPax,
IIF(Forms]![GeneralReport]![myCheckBox] = True,
p.PaymentDetailColumn1, NULL) AS PayColumn1,
IIF(Forms]![GeneralReport]![myCheckBox] = True,
p.PaymentDetailColumn2, NULL) AS PayColumn2,
IIF(Forms]![GeneralReport]![myCheckBox] = True,
p.PaymentDetailColumne, NULL) AS PayColumn3
...
FROM Main m
LEFT JOIN Payments p ON m.Invo = p.DueInvo
WHERE m.RecSrce <> 'Accounts'
AND m.InvoDate BETWEEN [Forms]![GeneralReport]![startDate]
AND [Forms]![GeneralReport]![endDate]
AND m.PartyId = NZ([Forms]![GeneralReport]![PartyID], m.PartyID)
AND m.Status = NZ([Forms]![GeneralReport]![Status], m.Status)
AND m.Ac1 = NZ([Forms]![GeneralReport]![Ac1], m.Ac1)
AND m.Ac2 = NZ([Forms]![GeneralReport]![Ac2], m.Ac2);
If you want dynamic columns (i.e., payment details) to appear or not depending on condition, this cannot come directly from SQL but some connecting app layer code (VBA, Python, etc.) to building dynamic queries. Recall SQL is a declarative language and once identifiers are assigned they are immutable. However, if using reports, you do want all columns explicitly defined from recordsource query.

SQL Server - WHERE inside CASE?

I'm fairly new to SQL Server and I'm having trouble implementing a WHERE statement inside a CASE, specifically for a trigger I'm working on.
I have 2 tables with the following fields:
Receipt(ItemID,Quantity)
and
Warehouses(WarehouseID,Stock)
|WarehouseID|Stock|
-------------------
|ARM01 |100 |
|ARM02 |100 |
The trigger checks whether a row with a specific quantity of any given item was inserted, altered or removed to Receipt and then subtracts or adds to the Stock of the Warehouses table.
So if I add a row with 200 Quantity in Receipt, it will subtract 100 from the Stock of WarehouseID 'ARM01', and if there is no Stock left in 'ARM01' (which there isn't because there is only 100), it will subtract the other 100 from 'ARM02'. Of course if 'ARM02' has a Stock of 0 it will print an error but I'll worry about that later.
The thing is, SQL Server doesn't accept a WHERE inside a CASE, because, of course, the entire CASE is already part of the SET statement and WHEREs only come after a SET. It's weird but I couldn't find an answer online yet for such a simple thing.
My goal:
CASE 1
UPDATE 'Stock of Table' where 'WarehouseID of Same Table' = 'ARM01'
CASE 2
UPDATE 'Stock of Table' where 'WarehouseID of Same Table' = 'ARM02'
I also realize the calculus for Stock -/+ Quantity and vice-versa might be wrong right now and I also have 2 statements in parenthesis after a THEN, separated by a AND because I was trying to distribute the first 100 to ARM01 and the rest to ARM02. That's probably very, very misguided and apologies for the incorrect code but for now I just want to figure out where to use a WHERE statement.
CREATE TRIGGER SubtractStock ON Receipt
FOR INSERT, UPDATE, DELETE
AS
[snipped UPDATE for deleted because it only exchanges '+' for '-' in the operation]
UPDATE Warehouses
SET Stock =
(CASE
WHEN inserted.Quantity <= Stock THEN Stock - Quantity WHERE WarehouseID = 'ARM01'
WHEN inserted.Quantity > Stock THEN (Stock - Quantity WHERE WarehouseID = 'ARM01')
AND (Quantity - Stock WHERE WarehouseID = 'ARM02')
END)
FROM inserted JOIN Warehouses ON inserted.ItemID = Warehouses.ItemID
Thank you!
I hate triggers, and this is a bad idea for one. With that out of the way.
For ARM01, move the WHERE to the WHEN with an AND:
SET Stock =
(CASE
WHEN inserted.Quantity <= Stock AND WarehouseID = 'ARM01'
THEN Stock - Quantity
...
The next problem is you need to see two rows to set the stock for ARM02, what the stock is in ARM02 to see if you need to subtract from ARM02, and the stock in ARM02 to subtract from. So moving the condition in the where somewhere else won't help. Probably two update statements, update ARM01, with an output clause to temp table or table valued variable to give before stock values for ARM01, then use that to update the values for ARM02.
Again, this sort of complicated logic rarely is appropriate inside a trigger.
Please try like this...Use proper aliases..
CREATE TRIGGER SubtractStock ON Receipt
FOR INSERT, UPDATE, DELETE
AS
UPDATE W
SET Stock = CASE
WHEN WarehouseID = 'ARM01' AND I.Quantity <= Stock THEN Stock - Quantity
WHEN WarehouseID = 'ARM01' AND I.Quantity > Stock THEN Stock - Quantity
WHEN WarehouseID = 'ARM02' THEN I.Quantity - Stock
END
FROM inserted I JOIN Warehouses W ON I.ItemID = W.ItemID

Prestashop - change product category in database

I need to mass change product categories. I updated two tables in database: ps_category_product (changed old id_category) and ps_products (changed old id_category_default) but in BO product table and webshop I still see old category (home).
When I edit product, select tab associations I see that product is associated with my new caterogy. Only when I save the product by click save button I see that product in properly categories.
I compared two rows in database (product with changed category by mysql query and product changed in BO) and these two look identical.
What am I doing wrong? I was trying clean cache (delete cache/cachefs and smarty/compile), disable all cache options but with no result.
To change the category, the following queries must be executed:
Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'category_product SET id_category = NEW_ID_CATEGORY WHERE id_category = OLD_ID_CATEGORY');
Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product_shop SET id_category_default = NEW_ID_CATEGORY WHERE id_category_default = OLD_ID_CATEGORY AND id_shop = ID_SHOP');
Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product SET id_category_default = NEW_ID_CATEGORY WHERE id_category_default = OLD_ID_CATEGORY');
Regards

SQL Create View - Sum Transactions on one line

I want to create a view, whereby all post stock transactions will post on one line, as per my SQL Statement below, I get all transactions, but each is on a new line. I want the arrangement to be each new stock item on a new line, with "QtyOnHand" as the next column. Then I need all the QtyOut transactions to sum up in one column and all QtyIn to sum in another. Is this possible?
SELECT
StkItem.ItemGroup
,StkItem.Qty_On_Hand AS QtyOnHand
,PostST.TrCodeID
,PostST.Description
,PostST.Quantity
,PostST.Reference
,PostST.Order_No
,PostST.fQuantityInvoiced
,PostST.QuantityR
,PostST.TxDate
,PostST.Debit
,PostST.Credit
,Concat(StkItem.Description_1, ' - ',StkItem.Code) AS ItemAndCode
FROM PostST
INNER JOIN StkItem
ON StkItem.StockLink = PostST.AccountLink
The below picture shows how this statement currently shows - you can see on the far right how the same stock code is repeated for each transaction, as I would rather the stock item show once, and the transactions be summed.
This data will be dumpted into Excel and then used to create a stock turnover report.
Thank you!
You have to use SUM() and GROUP BY. Maybe that is what you need
SELECT
StkItem.ItemGroup
,SUM(StkItem.Qty_On_Hand) AS QtyOnHand
,PostST.TrCodeID
,PostST.Description
,SUM(PostST.Quantity) as Quantity
,PostST.Reference
,PostST.Order_No
,SUM(PostST.fQuantityInvoiced) as fQuantityInvoiced
,SUM(PostST.QuantityR) as QuantityR
,PostST.TxDate
,SUM(PostST.Debit) as Debit
,SUM(PostST.Credit) as Credit
,Concat(StkItem.Description_1, ' - ',StkItem.Code) AS ItemAndCode
FROM PostST
INNER JOIN StkItem
ON StkItem.StockLink = PostST.AccountLink
GROUP BY
StkItem.ItemGroup
,PostST.TrCodeID
,PostST.Description
,PostST.Reference
,PostST.Order_No
,PostST.TxDate
,StkItem.Description_1
,StkItem.Code