Oracle SQL Update a column based on another table but based on a date - sql

Learning SQL so please forgive me.
I have a table that holds many accounts(and sub accounts) and another table that holds many orders they are custom tables taken from different databases.
What I am trying to do is update order_amt on the account table with the order_val value from the orders table but if there are more than one order with that account I want the order amount from the earliest order date only.
Account Table
Acc _Num..........Comp_Name.......Order_Amt.......Int_Id
123456789-1.....ABC Ltd.......................................123456789
123456789-2.....ABC Ltd.......................................123456789
987654321-1.....Xyz Ltd.........................................987654321
987654321-2.....Xyz Ltd.........................................987654321
Orders Table
Order_Num.....Order_Dt.....Order_Val.....Acc_num
1......................01/01/13......£20.00...........123456789
2......................01/01/14......£10.00...........123456789
3......................01/01/10......£100.00..........987654321
4......................01/01/11......£200.00..........987654321
So the order_amt for accounts 123456789-1 & 2 = £20.00 and from 987654321-1 & 2 would be £100.00.
UPDATE accounts a
SET a.order_amt =
(
SELECT order_val
FROM orders o
WHERE a.int_id = o.acc_num
AND EXISTS
(
SELECT MIN(order_dt)
FROM orders oa
WHERE o.order_num = oa.order_num
);
I am getting a few errors including the error that more than one row returned? Could anyone please help me?
kind Regards
Eden

I think you need something like this:
UPDATE accounts a
SET a.order_amt =
(
SELECT order_val
FROM orders o
WHERE a.int_id = o.acc_num
GROUP BY order_val
HAVING order_dt = MIN(order_dt);
);

Create a FK on the column account_number inside of the orders table and have it reference the auto-increment account id of the accounts table.
Then as Roger suggest, with the slight modification of the column int_id AND a modification of the HAVING clause
UPDATE accounts a
SET a.order_amount =
(
SELECT order_value
FROM orders o
WHERE a.account_number = o.account_number
GROUP BY order_value
HAVING MIN(order_date)
)
This will not fix the error that is occurring with more than one row being returned though since there are multiple orders with the same account id attached to them. You will need to be more specific about how what you are needing. Do you want the average of all order amounts to equal the order value in the accounts table? Or maybe the MAX/MIN value?

Related

Redshift - Finding number of times a particular values is store in a column in table

Given below is a view of my table that stores sale data along with the detail whether the customer is a new customer or not. I am trying to find if the same sale_id has multiple entries for the same customer and tags him as a new customer. Given below is a sample view of the table
cust_id,prod_id,sale_id,is_new_cust,store_type
1,prod_a,1001,t,store
2,prod_a,1002,,online
3,prod_a,1003,t,store
3,prod_a,1003,t,store
I need to find how many such customers exist that have the tag of is_new_cust for the same sale_id.
Given below is the SQL I tried:
select cust_id,count(is_new_cust) from sales
where store_type = 'store' and is_new_cust='t'
group by cust_id having count(is_new_cust)> 1;
Expected output:
cust_id,count
3,2
The above SQL returns 1 no results.
I am using Amazon Redshift DB for the above.
Could anyone help me find where am I going wrong with the query. Thanks..
I think you want:
select count(distinct cust_id) as num_customers,
count(distinct case when is_new_cust = 't' then cust_id end) as num_new_customers
from sales
where store_type = 'store';
However, this might be a simpler version that does what you want:
select count(*)
from sales
where store_type = 'store' and is_new_cust = 't';
This assumes the is_new_cust flag is set only once for a new customer.

Oracle SQL return sum of multiple across tables

Farily new to SQL and the IT world, and always do a lot of work before asking for help but this time I am stumped.
I have three tables:
So I am trying to update the "payment_owed" table by doing the following:
For each customer, get the food_id and quantity, then using the food_id multiply the quantity by the cost.
The best I have done this far is a natural join on the tables, and attempting to sum the quantity * cost for each ID
My understanding for updating a specific customer:
update customer
set payment_owed = (select <quantity>) * (select <cost>)
where cust_no = 1;
If im not on the right forum or there's a better place to ask these questions let me know, thank you for your time!
Simply:
update customer
set payment_owed = (SELECT SUM(o.cost*s.quantity)
FROM order o JOIN session s ON s.food_id = o.food_id
WHERE s.cust_no = customer.cust_no)
where cust_no = 1;
Anyway will you update it after every change on table? How about using view like:
CREATE VIEW my_view AS
SELECT cust_no, SUM(o.cost*s.quantity)
FROM order o
JOIN session s ON s.food_id = o.food_id
GROUP BY cust_no;

How can i SUM records from a table to another after multiplying two columns

I have a table called orderItems which has two columns, quantity and unit price.It also has a foreign key ordernumber in that very table.
I have another table called ordergroup with primary key ordernumber, which contains SavedTotal column which is the order total based on quantity * unit price for all order item rows that reference that ordernumber.
Now what i struggle with is the sql query that can get all order items based on a certain ordernumber and calculate the total cost.
I have managed to do the multiplication but i am missing the SUM, here is my sql query(based on SQL Server) so far.
UPDATE OrderGroupNew
set OrderGroupNew.SavedTotal = OrderItemNew.UnitPrice*OrderItemNew.QUANTITY
FROM OrderItemNew
inner join OrderGroupNew on OrderItemNew.OrderNumber=OrderGroupNew.OrderNumber
any help is appreciated
UPDATE OrderGroupNew
SET SavedTotal = (
SELECT SUM(UnitPrice * Quantity)
FROM OrderItemNew
WHERE OrderNumber = OrderGroupNew.OrderNumber
)
You can use a TVP as well :
;With o as (
select OrderItemNew.OrderNumber as OrderNumber,
SUM(OrderItemNew.UnitPrice*OrderItemNew.QUANTITY) as OrderSum
Group by OrderItemNew.OrderNumber)
UPDATE OrderGroupNew
set OrderGroupNew.SavedTotal = o.OrderSum
FROM o
INNER JOIN OrderGroupNew on o.OrderNumber=OrderGroupNew.OrderNumber
Well the 1st answer is correct too. Choose the best in term of performance :) (dont know which will be the best, to be honest ! )

Suppress Nonadjacent Duplicates in Report

Medical records in my Crystal Report are sorted in this order:
...
Group 1: Score [Level of Risk]
Group 2: Patient Name
...
Because patients are sorted by Score before Name, the report pulls in multiple entries per patient with varying scores - and since duplicate entries are not always adjacent, I can't use Previous or Next to suppress them. To fix this, I'd like to only display the latest entry for each patient based on the Assessment Date field - while maintaining the above order.
I'm convinced this behavior can be implemented with a custom SQL command to only pull in the latest entry per patient, but have had no success creating that behavior myself. How can I accomplish this compound sort?
Current SQL Statement in use:
SELECT "EpisodeSummary"."PatientID",
"EpisodeSummary"."Patient_Name",
"EpisodeSummary"."Program_Value"
"RiskRating"."Rating_Period",
"RiskRating"."Assessment_Date",
"RiskRating"."Episode_Number",
"RiskRating"."PatientID",
"Facility"."Provider_Name",
FROM (
"SYSTEM"."EpisodeSummary"
"EpisodeSummary"
LEFT OUTER JOIN "FOOBARSYSTEM"."RiskAssessment" "RiskRating"
ON (
("EpisodeSummary"."Episode_Number"="RiskRating"."Episode_Number")
AND
("EpisodeSummary"."FacilityID"="RiskRating"."FacilityID")
)
AND
("EpisodeSummary"."PatientID"="RiskRating"."PatientID")
), "SYSTEM"."Facility" "Facility"
WHERE (
"EpisodeSummary"."FacilityID"="Facility"."FacilityID"
)
AND "RiskRating"."PatientID" IS NOT NULL
ORDER BY "EpisodeSummary"."Program_Value"
The SQL code below may not be exactly correct, depending on the structure of your tables. The code below assumes the 'duplicate risk scores' were coming from the RiskAssessment table. If this is not correct, the code may need to be altered.
Essentially, we create a derived table and create a row_number for each record, based on the patientID and ordered by the assessment date - The most recent date will have the lowest number (1). Then, on the join, we restrict the resultset to only select record #1 (each patient has its own rank #1).
If this doesn't work, let me know and provide some table details -- Should the Facility table be the starting point? are there multiple entries in EpisodeSummary per patient? thanks!
SELECT es.PatientID
,es.Patient_Name
,es.Program_Value
,rrd.Rating_Period
,rrd.Assessment_Date
,rrd.Episode_Number
,rrd.PatientID
,f.Provider_Name
FROM SYSTEM.EpisodeSummary es
LEFT JOIN (
--Derived Table retreiving highest risk score for each patient)
SELECT PatientID
,Assessment_Date
,Episode_Number
,FacilityID
,Rating_Period
,ROW_NUMBER() OVER (
PARTITION BY PatientID ORDER BY Assessment_Date DESC
) AS RN -- This code generates a row number for each record. The count is restarted for every patientID and the count starts at the most recent date.
FROM RiskAssessment
) rrd
ON es.patientID = rrd.patientid
AND es.episode_number = rrd.episode_number
AND es.facilityid = rrd.facilityid
AND rrd.RN = 1 --This only retrieves one record per patient (the most recent date) from the riskassessment table
INNER JOIN SYSTEM.Facility f
ON es.facilityid = f.facilityid
WHERE rrd.PatientID IS NOT NULL
ORDER BY es.Program_Value

SQL-Oracle: Updating table column with sum of values from another table - using common key column/s criteria

Good Evening Stackoverflow team/members
Oracle version: 11g Release 11.1.0.6.0 - 64bit Production
I have two Tables: ORDERS and ITEMS.
ORDERS looks like this
ORDERS
ITEMS looks like this
enter image description here
Table ORDERS has 1 or more Order_Number each assigned to at least one depot or more. the column Total_Value SHOULD store exactly the sum of the item values associated to an order number. the table ITEMS in fact stores via parcel_code items values for a specific order_number/s.
my db has a bug for orders that have more than one depot assigned to an order number (e.g. order number 1 and 4) do not store the actual total value correctly.
in my case I cannot figure out the UPDATE statement that would select order numbers that would take the sum from the table ITEMS and link it via parcel_code and update the column total_value in the table ORDERS.
the result of my update should give this back:
for table orders i should get back for
order number 1:
for both rows total value 1120
order number 4
for both rows total value: 350
order number 2 and 3 as they are single depot order remain the same:
50 and 20
pseudo-code :
update ORDERS
set total_value = (select sum(I.item_value) from ITEMS I, ORDERS O where O.parcel_code = I.parcel_code)
i would update also those orders which have on e depot assigned as they will exactly the same.
i was looking at MERGE statements or INNER select queries. the problem i am facing is that my update must be dynamic. this means not driven by values but by columns joins as i may have to create a process that update this every day.
can someone help me?
You need to join the items and orders tables together, then select the sum of all item_values where your order_number is equal to the row which you are updating (in table o1).
update
Orders o1
set o1.total_value = (
select sum(i.item_value) from Items i
join Orders o2 on o2.parcel_code = i.parcel_code
where o2.Order_number = o1.Order_number
)