Oracle update statement using multiple columns - sql

I am trying to update price of my products, using another table which has product material and number of that material
my tables are produkt (PRODUKTID int, NAZOV varchar(47), VYROBNA_CENA int)
TABLE material (MATERIALID int, CENA numeric);
TABLE zlozenie (PRODUKTKID int, MATERIALID int, MNOZSTVO int);
what i am trying to do is to put sum(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) to column VYROBNA_CENA
i have two selects that are returning same column, but i am not sure how to use update to transfer values from one to another
first one - calculated price of products
select PRODUKT.NAZOV as NAZOV, sum(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) as celkova
from MATERIAL, PRODUKT, ZLOZENIE
where ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
and PRODUKT.PRODUKTID=ZLOZENIE.PRODUKTKID
group by PRODUKT.NAZOV
order by PRODUKT.NAZOV
second one is table produkt with empty price(cena), and i would like to put results from sum to column cena
select PRODUKT.NAZOV, PRODUKT.vyrobna_cena
from PRODUKT
order by PRODUKT.NAZOV
sql fiddle with tables and queries http://sqlfiddle.com/#!2/e183f/2
thanks

MERGE INTO produkt p
USING
(
SELECT ZLOZENIE.PRODUKTKID, SUM(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) AS celkova
FROM MATERIAL, ZLOZENIE
WHERE ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
GROUP BY ZLOZENIE.PRODUKTKID
) s
ON (p.PRODUKTID = s.PRODUKTKID)
WHEN MATCHED THEN
UPDATE SET VYROBNA_CENA = s.celkova;
Although I would always use join syntax
MERGE INTO produkt p
USING
(
SELECT ZLOZENIE.PRODUKTKID, SUM(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) as celkova
FROM MATERIAL
JOIN ZLOZENIE ON ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
GROUP BY ZLOZENIE.PRODUKTKID
) s
ON (p.PRODUKTID = s.PRODUKTKID)
WHEN MATCHED THEN
UPDATE SET VYROBNA_CENA = s.celkova

Following work is based on your sql fiddle and mysql database.
Change all the decimal columns in your creation scripts from integers to decimal. Following are the updated creation scripts
CREATE TABLE produkt
(`PRODUKTID` int, `NAZOV` varchar(47), `VYROBNA_CENA` decimal(10,2));
CREATE TABLE zlozenie
(`PRODUKTKID` int, `MATERIALID` int, `MNOZSTVO` decimal(10,5));
CREATE TABLE material
(`MATERIALID` int, `CENA` decimal(10,2));
sqlfiddle with updated tables and queries : http://sqlfiddle.com/#!2/0242f/6
Query to update the produckt table
update produkt INNER JOIN
(select ZLOZENIE.PRODUKTKID,sum(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) as celkova
from MATERIAL, ZLOZENIE
where ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
group by ZLOZENIE.PRODUKTKID) ZM
on produkt.PRODUKTKID = ZM.PRODUKTKID
set produkt.VYROBNA_CENA = ZM.celkova
Let me know if this is not what you are after

Related

Updating fields based on results of a query

So in this scenario a person can order products. I have a query that returns the result of an order ID and give the products that person ordered.
My issue is adapting this to an update query so the quantity from the OrderProduct table/query is then subtracted from the amount of stock in the Product Table.
SQL to create the table supplied below and the query to get the results
CREATE DATABASE StockControl;
CREATE TABLE Membership (
MemberID int NOT Null,
LastName varchar(255),
FirstName varchar(255),
Primary Key(MemberID)
);
CREATE TABLE Orders (
OrderID int NOT Null,
MemberID int,
Primary Key(OrderID)
);
CREATE TABLE Product (
ProductID int NOT Null,
Price int,
Stock int,
Primary Key(ProductID)
);
CREATE TABLE OrderProduct (
ProductID int,
OrderID int,
Quantity int
);
INSERT INTO Membership(MemberID,LastName,FirstName)
VALUES (2,'Me','Too'),(33,'Darren','Kelly');
INSERT INTO Orders(OrderID,MemberID)
VALUES (1,33),(5,2);
INSERT INTO Product(ProductID,Price,Stock)
VALUES (1,30,12),(2,25,12),(3,25,12),(4,25,12),(5,25,12),(6,25,12),(7,25,12),(8,25,12),(9,25,12),(10,25,12);
INSERT INTO OrderProduct(ProductID,OrderID,Quantity)
VALUES (1,5,1),(3,1,4),(9,1,6),(10,1,2);
This is the query to return all products as part of orderID 1, in the full version this will be able to be variable.
SELECT OrderProduct.ProductID, OrderProduct.OrderID, OrderProduct.Quantity, Product.Price, [Quantity]*[Price] AS Cost
FROM Product INNER JOIN OrderProduct ON Product.ProductID = OrderProduct.ProductID
GROUP BY OrderProduct.ProductID, OrderProduct.OrderID, OrderProduct.Quantity, Product.Price, [Quantity]*[Price]
HAVING (((OrderProduct.OrderID)=1))
ORDER BY OrderProduct.OrderID;
This returns the correct result but when trying to implement this to an update I get stuck. I want it so it looks through the 3 results and will subtract 4 from product 3, 6 from product 9 and 2 from product 10
Attempt so far
UPDATE SingleOrder INNER JOIN Product ON SingleOrder.ProductID = Product.ProductID SET Product.Stock = Product.Stock-SingleOrder.Quantity WHERE ((Product.ProductID=SingleOrder.ProductID));
If this is not clear I am happy to update the question etc.
Thanks

Invalid Object Name when i execute a procedure that update a table

I have the following
use salesdb
go
create procedure monthlysales as
begin
create table MyTable( SalesFactID integer identity(1,1),
ReportingMth date,
customer_id varchar(50),
ReferenceID navarchar(50),
LstOrderDte date);
Insert into MyTable
select
businessMth,
saleid as referenceid,
null as lastorderte
from sourcetble;
update MyTable
set lastorderte = sls.max_orderdte
from ( select
st.customer_id,
ftmytbl.ReportingMth,
max(salesdate) as max_orderdte
from sales_table st
left outer join mytable ftmytbl
on ftmytbl.customerid=st.customerRef
where saleste<=ftmytbl.ReportingMth
group by customer_id
)up
where mytable.customer_id=up.customer_id
and mytable.reportingmth=up.ReportingMth;
end;
execute monthlysales
error invalid object name mytable.reportingmth
How can i fix this? Please assist.
Search for that text. Where is it? It is in the where clause of the outermost select statement. You used a derived table named up (which is a crap name, btw - as are many of your names) in the join. The outer query knows only 2 tables - up and MyTable (or is it mytable? BE CONSISTENT!) and can only refer to columns in those tables.
To correct this particular problem, change this:
and mytable.reportingmth=up.ReportingMth;
to
and MyTable.ReportingMth = up.ReportingMth;
But that will only fix one problem. There seem to be others yet to be found.

The aggregate expression cannot be used in the WHERE clause

I have the following tables in my database:
The first table is named Amount, second Product, third Purchase.
And I should to create the trigger on insert to amount table. For example, I'll insert the following values: 4, 1, 10, where 4 is id_purchase, 1 is id_product and 4 is amount of this products. And trigger should subtract this amount from Amount_On_Stock. In my example, it should be: was 48, became 38.
Here's the code of my trigger:
CREATE TRIGGER AmountInsert ON Amount
AFTER INSERT
AS
BEGIN
UPDATE Product
SET Amount_On_Stock = (
SELECT
Amount_On_Stock
FROM Product
WHERE ID_Product = (
SELECT
MAX(ID_Product)
FROM Purchase
WHERE ID_Purchase = (
SELECT
MAX(ID_Purchase)
FROM Purchase
)
)
)-(
SELECT
Amount
FROM AMOUNT
WHERE ID_Product = (
SELECT
MAX(ID_Product)
FROM Purchase
WHERE ID_Purchase = (
SELECT
MAX(ID_Purchase)
FROM Purchase
)
)
)
END
But when I try to create this trigger I have the following error:
The aggregate expression cannot be used in the WHERE clause unless it
is contained in a subquery of the HAVING clause or in the select list,
and the column being aggregated is not an external reference.
So, how can I solve this problem?
Your trigger looks nothing like a SQL Server trigger. I would expect your trigger to look more like this:
CREATE TRIGGER AmountInsert ON Amount AFTER INSERT
AS
BEGIN
UPDATE p
SET Amount_On_Stock = p.Amount_On_Stock - i.amount
FROM Product p JOIN
inserted i
ON p.ID_Product = i.ID_Product;
END;
However, this will not do the right thing if you have multiple inserts on the same product at the same time. To handle that you need aggregation:
CREATE TRIGGER AmountInsert ON Amount AFTER INSERT
AS
BEGIN
UPDATE p
SET Amount_On_Stock = p.Amount_On_Stock - i.amount
FROM Product p JOIN
(SELECT i.ID_Product, SUM(i.amount) as amount
FROM inserted i
GROUP BY i.ID_Product
) i
ON p.ID_Product = i.ID_Product;
END;

SQL Server 2008 R2: Show only recently added records

I have two tables:
Cust : Contains customer details like customer ID and customer Name.
Cust_Address : This table contains customer ID and customer address.
Table: Cust
create table cust
(
cust_id int,
cust_name varchar(10)
);
Records Insertion:
insert into cust values(1,'A');
insert into cust values(2,'B');
insert into cust values(3,'C');
insert into cust values(4,'D');
Table: Cust_Address
create table cust_address
(
cust_id int,
cust_add varchar(50)
);
Records Insertion:
insert into cust_address values(1,'US');
insert into cust_address values(2,'UK');
insert into cust_address values(3,'UAE');
insert into cust_address values(4,'SA');
insert into cust_address values(1,'AUS');
insert into cust_address values(2,'IND');
insert into cust_address values(3,'SL');
insert into cust_address values(1,'CHINA');
Now I want to show the result which contains the latest customer address which have been inserted in the table Cust_Address.
Expected Result:
Cust_ID Cust_Name Cust_Add
-------------------------------
1 A CHINA
2 B IND
3 C SL
4 D SA
Here is the SQLFiddle for tables and its records.
You are not able to retrieve the rows in any particular order. You need some more info to get an order.
The best way is primary index in Cust_address
CustAddrID int identity(1, 1) not null primary key
You can also have a CreatedOn column that will have default value equal to getDate()
After that you can figure out what is the last inserted value for CustAddr for each Cust record.
In case you are not able to add new column there then maybe
change tracking functionality. But your issue seems to be too trivial for that.
There are also Temporal Tables in SQL Server 2016. But again it's probably too much.
Here is an example how you can get the address using primary key CustAddrID
SQL Fiddle
select cust_name, cust_add
from cust C
join
(select
cust_add, cust_id,
row_number() over (partition by cust_id order by cust_add_id desc) rn
from cust_address ) CLA
on CLA.cust_id = C.cust_id and
CLA.rn = 1
Identity column increases every time when we insert new value to the table. The correct value for your case will be the record with the highest cust_add_id and specified cust_id.
In the above query we generates numbers in desc order starting from 1 using row_number() function for each cust_id (partition by cust_id). Finally we take only the records with generated number rn equal to 1 CLA.rn = 1 and we join it to cust table.
You can replace row_number() by max(cust_add_id) and group by cust_id. However in that case you need to join cust_add table twice.
You will not be able to get the rows out of the link table in the order they were inserted.
You need to have a column for this.
Imagine how big the meta-data would be if you needed to keep a record for each record for creation! Would you also want to keep meta-data on your meta-data so you know when the meta-data was updated? The space use can quickly escalate.
SQL Server keeps some stats but something this specific will need to come from a user-defined field.
So you either use a identity column in the CustAddr table [CustAddr int identity(1, 1) not null primary key] or add a column for createdDateAndTime DateTime Default GetDate().

Oracle SQL Out put two table at a query

CREATE TABLE Products (
ID int,
name VARCHAR(70),
price NUMBER(8,2),
primary key (ID, name)
);
drop table Instock;
/* Delete the tables if they already exist */
create table Instock (
ID int,
quantity int
);
I have two table in my database. i want to have two table showing a output as a table that look like this
ID Name Price Quantity
SELECT A.ID,A.NAME,A.PRICE,B.QUANTITY FROM Products A,Instock B WHERE A.ID=B.ID
You can try this to create the new table(this creates the table in addition to putting the data in there)
CREATE TABLE MY_TABLE as SELECT A.ID,A.NAME,A.PRICE,B.QUANTITY FROM Products A,Instock B WHERE A.ID=B.ID