Splitting Column Headers and Duplicating Row Values in Pandas Dataframe - pandas

In the example df below, I'm trying to find a way to split the column headers ('1;2','4','5;6') based on the ';' that exists and duplicate the row values in these split columns. (My actual df comes from an imported csv file so generally I have around 50-80 column headers that need spliting)
Below is my code below with output
import pandas as pd
import numpy as np
#
data = np.array([['Market','Product Code','1;2','4','5;6'],
['Total Customers',123,1,500,400],
['Total Customers',123,2,400,320],
['Major Customer 1',123,1,100,220],
['Major Customer 1',123,2,230,230],
['Major Customer 2',123,1,130,30],
['Major Customer 2',123,2,20,10],
['Total Customers',456,1,500,400],
['Total Customers',456,2,400,320],
['Major Customer 1',456,1,100,220],
['Major Customer 1',456,2,230,230],
['Major Customer 2',456,1,130,30],
['Major Customer 2',456,2,20,10]])
df =pd.DataFrame(data)
df.columns = df.iloc[0]
df = df.reindex(df.index.drop(0))
print (df)
0 Market Product Code 1;2 4 5;6
1 Total Customers 123 1 500 400
2 Total Customers 123 2 400 320
3 Major Customer 1 123 1 100 220
4 Major Customer 1 123 2 230 230
5 Major Customer 2 123 1 130 30
6 Major Customer 2 123 2 20 10
7 Total Customers 456 1 500 400
8 Total Customers 456 2 400 320
9 Major Customer 1 456 1 100 220
10 Major Customer 1 456 2 230 230
11 Major Customer 2 456 1 130 30
12 Major Customer 2 456 2 20 10
Below is my desired output
0 Market Product Code 1 2 4 5 6
1 Total Customers 123 1 1 500 400 400
2 Total Customers 123 2 2 400 320 320
3 Major Customer 1 123 1 1 100 220 220
4 Major Customer 1 123 2 2 230 230 230
5 Major Customer 2 123 1 1 130 30 30
6 Major Customer 2 123 2 2 20 10 10
7 Total Customers 456 1 1 500 400 400
8 Total Customers 456 2 2 400 320 320
9 Major Customer 1 456 1 1 100 220 220
10 Major Customer 1 456 2 2 230 230 230
11 Major Customer 2 456 1 1 130 30 30
12 Major Customer 2 456 2 2 20 10 10
Ideally I would like to perform such a task at the 'read_csv' level. Any thoughts?

Try reindex with repeat
s=df.columns.str.split(';')
df=df.reindex(columns=df.columns.repeat(s.str.len()))
df.columns=sum(s.tolist(),[])
df
Out[247]:
Market Product Code 1 2 4 5 6
1 Total Customers 123 1 1 500 400 400
2 Total Customers 123 2 2 400 320 320
3 Major Customer 1 123 1 1 100 220 220
4 Major Customer 1 123 2 2 230 230 230
5 Major Customer 2 123 1 1 130 30 30
6 Major Customer 2 123 2 2 20 10 10
7 Total Customers 456 1 1 500 400 400
8 Total Customers 456 2 2 400 320 320
9 Major Customer 1 456 1 1 100 220 220
10 Major Customer 1 456 2 2 230 230 230
11 Major Customer 2 456 1 1 130 30 30
12 Major Customer 2 456 2 2 20 10 10

You can split the columns with ';' and then reconstruct a df:
pd.DataFrame({c:df[t] for t in df.columns for c in t.split(';')})
Out[157]:
1 2 4 5 6 Market Product Code
1 1 1 500 400 400 Total Customers 123
2 2 2 400 320 320 Total Customers 123
3 1 1 100 220 220 Major Customer 1 123
4 2 2 230 230 230 Major Customer 1 123
5 1 1 130 30 30 Major Customer 2 123
6 2 2 20 10 10 Major Customer 2 123
7 1 1 500 400 400 Total Customers 456
8 2 2 400 320 320 Total Customers 456
9 1 1 100 220 220 Major Customer 1 456
10 2 2 230 230 230 Major Customer 1 456
11 1 1 130 30 30 Major Customer 2 456
12 2 2 20 10 10 Major Customer 2 456
Or if you would like to reserve column order:
pd.concat([df[t].to_frame(c) for t in df.columns for c in t.split(';')],1)
Out[167]:
Market Product Code 1 2 4 5 6
1 Total Customers 123 1 1 500 400 400
2 Total Customers 123 2 2 400 320 320
3 Major Customer 1 123 1 1 100 220 220
4 Major Customer 1 123 2 2 230 230 230
5 Major Customer 2 123 1 1 130 30 30
6 Major Customer 2 123 2 2 20 10 10
7 Total Customers 456 1 1 500 400 400
8 Total Customers 456 2 2 400 320 320
9 Major Customer 1 456 1 1 100 220 220
10 Major Customer 1 456 2 2 230 230 230
11 Major Customer 2 456 1 1 130 30 30
12 Major Customer 2 456 2 2 20 10 10

Related

MS-Access - Merge data between two tables base on conditions

I am using MS Access and I am trying to create a query between two tables and merge same rows base on:
cust_id = cust_id and
a_date = f_date and
price = paid
and have the desire output.
My data now:
tblapp
app_id cust_id a_date price a_memo
------------------------------------------
1 1 10/10/20 20 hello
2 1 11/10/20 10 bye
3 2 12/10/20 30 hi
4 2 12/10/20 30 text
5 2 12/10/20 30 lol
6 2 12/10/20 30 ciao
7 3 14/10/20 25 peace
tblfin
fin_id cust_id f_date paid
----------------------------------
1 1 10/10/20 20
2 1 11/10/20 10
3 1 11/10/20 10
4 2 12/10/20 30
5 3 14/10/20 25
As you can see,
cust_id = 1 on 10/10/20 with bill 20 and paid 20
cust_id = 1 on 11/10/20 with bill 10 and paid 10 + 10
cust_id = 2 on 12/10/20 with bill 30 + 30 + 30 + 30 and paid 30
cust_id = 3 on 14/10/20 with bill 25 and paid 25
Derire query output:
app_id cust_id a_date price a_memo fin_id cust_id f_date paid
----------------------------------------------------------------------
1 1 10/10/20 20 hello 1 1 10/10/20 20
2 1 11/10/20 10 bye 2 1 11/10/20 10
3 2 12/10/20 30 hi 4 2 12/10/20 30
7 3 14/10/20 25 peace 5 3 14/10/20 25
Tried the following sql but i am getting duplicates(like cust_id 1 and 2 where data rows are not the same in two tables):
SELECT f.fin_id,
f.cust_id,
f.f_date,
f.paid,
a.app_id,
a.cust_id,
a.a_date,
a.price,
a.a_memo
FROM tblfin AS f
LEFT JOIN tblapp AS a ON (f.cust_id=a.cust_id)
AND (f.f_date=a.a_date)
AND (f.paid=a.price);
Solution using MySQL is welcome. Thank you.

groupby sum month wise on date time data

I have a transaction data as shown below. which is a 3 months data.
Card_Number Card_type Category Amount Date
0 1 PLATINUM GROCERY 100 10-Jan-18
1 1 PLATINUM HOTEL 2000 14-Jan-18
2 1 PLATINUM GROCERY 500 17-Jan-18
3 1 PLATINUM GROCERY 300 20-Jan-18
4 1 PLATINUM RESTRAUNT 400 22-Jan-18
5 1 PLATINUM HOTEL 500 5-Feb-18
6 1 PLATINUM GROCERY 400 11-Feb-18
7 1 PLATINUM RESTRAUNT 600 21-Feb-18
8 1 PLATINUM GROCERY 800 17-Mar-18
9 1 PLATINUM GROCERY 200 21-Mar-18
10 2 GOLD GROCERY 1000 12-Jan-18
11 2 GOLD HOTEL 3000 14-Jan-18
12 2 GOLD RESTRAUNT 500 19-Jan-18
13 2 GOLD GROCERY 300 20-Jan-18
14 2 GOLD GROCERY 400 25-Jan-18
15 2 GOLD HOTEL 1500 5-Feb-18
16 2 GOLD GROCERY 400 11-Feb-18
17 2 GOLD RESTRAUNT 600 21-Mar-18
18 2 GOLD GROCERY 200 21-Mar-18
19 2 GOLD HOTEL 700 25-Mar-18
20 3 SILVER RESTRAUNT 1000 13-Jan-18
21 3 SILVER HOTEL 1000 16-Jan-18
22 3 SILVER GROCERY 500 18-Jan-18
23 3 SILVER GROCERY 300 23-Jan-18
24 3 SILVER GROCERY 400 28-Jan-18
25 3 SILVER HOTEL 500 5-Feb-18
26 3 SILVER GROCERY 400 11-Feb-18
27 3 SILVER HOTEL 600 25-Mar-18
28 3 SILVER GROCERY 200 29-Mar-18
29 3 SILVER RESTRAUNT 700 30-Mar-18
I am struggling to get below dataframe.
Card_No Card_Type D Jan_Sp Jan_N Feb_Sp Feb_N Mar_Sp GR_T RES_T
1 PLATINUM 70 3300 5 1500 3 1000 2300 100
2 GOLD 72 5200 5 1900 2 1500 2300 1100
3 SILVER . 76 2900 5 900 2 1500 1800 1700
D = Duration in days from first transaction to last transaction.
Jan_Sp = Total spending on January.
Feb_Sp = Total spending on February.
Mar_Sp = Total spending on March.
Jan_N = Number of transaction in Jan.
Feb_N = Number of transaction in Feb.
GR_T = Total spending on GROCERY.
RES_T = Total spending on RESTRAUNT.
I tried following code. I am very new to pandas.
q9['Date'] = pd.to_datetime(Card_Number['Date'])
q9 = q9.sort_values(['Card_Number', 'Date'])
q9['D'] = q9.groupby('ID')['Date'].diff().dt.days
My approach is three steps
get the date range
get the Monthly spending
get the category spending
Step 1: Date
date_df = df.groupby('Card_type').Date.apply(lambda x: (x.max()-x.min()).days)
Step 2: Month
month_df = (df.groupby(['Card_type', df.Date.dt.month_name().str[:3]])
.Amount
.agg({'sum','count'})
.rename({'sum':'_Sp', 'count': '_N'}, axis=1)
.unstack('Date')
)
# rename
month_df.columns = [b+a for a,b in month_df.columns]
Step 3: Category
cat_df = df.pivot_table(index='Card_type',
columns='Category',
values='Amount',
aggfunc='sum')
# rename
cat_df.columns = [a[:2]+"_T" for a in cat_df.columns]
And finally concat:
pd.concat( (date_df, month_df, cat_df), axis=1)
gives:
Date Feb_Sp Jan_Sp Mar_Sp Feb_N Jan_N Mar_N GR_T HO_T RE_T
Card_type
GOLD 72 1900 5200 1500 2 5 3 2300 5200 1100
PLATINUM 70 1500 3300 1000 3 5 2 2300 2500 1000
SILVER 76 900 3200 1500 2 5 3 1800 2100 1700
If your data have several years, and you want to separate them by year, then you can add df.Date.dt.year in each groupby above:
date_df = df.groupby([df.Date.dt.year,'Card_type']).Date.apply(lambda x: (x.max()-x.min()).days)
month_df = (df.groupby([df.Date.dt.year,'Card_type', df.Date.dt.month_name().str[:3]])
.Amount
.agg({'sum','count'})
.rename({'sum':'_Sp', 'count': '_N'}, axis=1)
.unstack(level=-1)
)
# rename
month_df.columns = [b+a for a,b in month_df.columns]
cat_df = (df.groupby([df.Date.dt.year,'Card_type', 'Category'])
.Amount
.sum()
.unstack(level=-1)
)
# rename
cat_df.columns = [a[:2]+"_T" for a in cat_df.columns]
pd.concat((date_df, month_df, cat_df), axis=1)
gives:
Date Feb_Sp Jan_Sp Mar_Sp Feb_N Jan_N Mar_N GR_T HO_T
Date Card_type
2017 GOLD 72 1900 5200 1500 2 5 3 2300 5200
PLATINUM 70 1500 3300 1000 3 5 2 2300 2500
SILVER 76 900 3200 1500 2 5 3 1800 2100
2018 GOLD 72 1900 5200 1500 2 5 3 2300 5200
PLATINUM 70 1500 3300 1000 3 5 2 2300 2500
SILVER 76 900 3200 1500 2 5 3 1800 2100
I would recommend keeping the dataframe this way, so you can access the annual data, e.g. result_df.loc[2017] gives you 2017 data. If you really want 2017 as year, you can do result_df.unstack(level=0).

pandas groupby sum, count by date time, where consider only year

I have a transaction data as shown below. which is a 3 months data.
Card_Number Card_type Category Amount Date
0 1 PLATINUM GROCERY 100 10-Jan-18
1 1 PLATINUM HOTEL 2000 14-Jan-18
2 1 PLATINUM GROCERY 500 17-Jan-18
3 1 PLATINUM GROCERY 300 20-Jan-18
4 1 PLATINUM RESTRAUNT 400 22-Jan-18
5 1 PLATINUM HOTEL 500 5-Feb-19
6 1 PLATINUM GROCERY 400 11-Feb-19
7 1 PLATINUM RESTRAUNT 600 21-Feb-19
8 1 PLATINUM GROCERY 800 17-Mar-17
9 1 PLATINUM GROCERY 200 21-Mar-17
10 2 GOLD GROCERY 1000 12-Jan-18
11 2 GOLD HOTEL 3000 14-Jan-18
12 2 GOLD RESTRAUNT 500 19-Jan-18
13 2 GOLD GROCERY 300 20-Jan-18
14 2 GOLD GROCERY 400 25-Jan-18
15 2 GOLD HOTEL 1500 5-Feb-19
16 2 GOLD GROCERY 400 11-Feb-19
17 2 GOLD RESTRAUNT 600 21-Mar-17
18 2 GOLD GROCERY 200 21-Mar-17
19 2 GOLD HOTEL 700 25-Mar-17
20 3 SILVER RESTRAUNT 1000 13-Jan-18
21 3 SILVER HOTEL 1000 16-Jan-18
22 3 SILVER GROCERY 500 18-Jan-18
23 3 SILVER GROCERY 300 23-Jan-18
24 3 SILVER GROCERY 400 28-Jan-18
25 3 SILVER HOTEL 500 5-Feb-19
26 3 SILVER GROCERY 400 11-Feb-19
27 3 SILVER HOTEL 600 25-Mar-17
28 3 SILVER GROCERY 200 29-Mar-17
29 3 SILVER RESTRAUNT 700 30-Mar-17
I am struggling to get below dataframe.
Card_No Card_Type D 2018_Sp 2018_N 2019_Sp 2019_N 2018_Sp
1 PLATINUM 70 3300 5 1500 3 1000
2 GOLD 72 5200 5 1900 2 1500
3 SILVER . 76 2900 5 900 2 1500
D = Duration in days from first transaction to last transaction.
2018_Sp = Total spending on year 2018.
2019_Sp = Total spending on 2019.
2017_Sp = Total spending on 2017.
2018_N = Number of transaction in 2018.
2019_N = Number of transaction in 2019.
Use:
#convert to datetimes
df['Date'] = pd.to_datetime(df['Date'])
#sorting if necessary
df = df.sort_values(['Card_Number','Card_type', 'Date'])
#aggregate count and sum
df1 = (df.groupby(['Card_Number','Card_type', df['Date'].dt.year])['Amount']
.agg([('Sp','size'),('N','sum')])
.unstack()
.sort_index(axis=1, level=1))
#MultiIndex to columns
df1.columns = [f'{b}_{a}' for a, b in df1.columns]
#difference (different output, because different years)
s = df.groupby('Card_type').Date.apply(lambda x: (x.max()-x.min()).days).rename('D')
#join together
df1 = df1.join(s).reset_index()
print (df1)
Card_Number Card_type 2017_N 2017_Sp 2018_N 2018_Sp 2019_N 2019_Sp \
0 1 PLATINUM 1000 2 3300 5 1500 3
1 2 GOLD 1500 3 5200 5 1900 2
2 3 SILVER 1500 3 3200 5 900 2
D
0 706
1 692
2 688

Selecting Dates From a table as Column Headers

i have a Table like this
ID Date Product_id Inventory
1 2/1/2017 1 180
2 9/1/2017 1 167
3 16/1/2017 1 320
4 23/1/2017 1 500
5 30/1/2017 1 20
How to write a SQL query on the table above to fetch a result like below
product_id 2/1/2017 9/1/2017 16/1/2017 23/1/2017 30/1/2017 ....
1 180 167 320 50 20

Update or Select into ORACLE

I am using the following statement;
SELECT RESV_ID, BOOKING_CUS_ID, ACC_ID,
(SELECT F.FLI_PRICE FROM FLIGHT F WHERE F.FLI_ID = R.IN_FLIGHT_ID) AS DEPART_FLIGHT_PRICE,
(SELECT F1.FLI_PRICE FROM FLIGHT F1 WHERE F1.FLI_ID = R.OUT_FLIGHT_ID) AS RETURN_FLIGHT_PRICE,
(SELECT AC.ACC_PRICEPN FROM ACCOMMODATION AC WHERE AC.ACC_ID = R.ACC_ID) AS ACCOMMODATION_PRICE
FROM HOLIDAY_RESERVATION R;
to yield the following results;
RESV_ID BOOKING_CUS_ID ACC_ID DEPART_FLIGHT_PRICE RETURN_FLIGHT_PRICE ACCOMMODATION_PRICE
---------- -------------- ---------- ------------------- ------------------- -------------------
1 1 2 520 450 350
2 3 4 250 150 150
3 5 6 290 300 450
4 7 7 399 450 650
5 9 365 345
6 11 558 460
7 13 250 250
8 15 550 550
9 17 25 250
10 19 19 450
10 rows selected.
Question:
How do I sum up the price fields, SOME PRICES ARE NOT AVAILABLE because a reservation was either made for accommodation only or flight only, hence both values will not be present always and this is where the issue lies
DEPART_FLIGHT_PRICE RETURN_FLIGHT_PRICE ACCOMMODATION_PRICE
Furthermore:
I wish to insert or update the SUM of those three values into a SUBTOTAL in the reservation table, perhaps by using select into or update, I have spent a whole day trying to do this but my skills are limited. any help will be greatly appreciated.
Flight table
FLI_ID FLI_CO FLI_AIRCRA DEPT_AIRPORT ARRV_AIRPORT DEPT_TIME ARRV_TIME FLI_PRICE
1 BD425 Boeing 707 1 12 18-MAR-12 02.24.00 AM 18-MAR-12 06.24.00 AM 520
2 LX345 Beriev 30 6 7 20-MAR-12 03.30.00 PM 20-MAR-12 04.20.00 PM 250
3 NZ4445 Boeing 720 9 14 25-MAR-12 09.00.00 AM 25-MAR-12 05.00.00 PM 290
4 TP351 Boeing 767 10 15 25-MAR-12 11.25.00 AM 25-MAR-12 03.35.00 PM 399
5 BA472 Boeing 720 5 14 26-MAR-12 01.05.00 PM 26-MAR-12 04.15.00 PM 365
Accommodation
ACC_ID ACC_TYPE_CODE ACC_DESC ACC_PRICEPN ACC_ROOMS RESORT_ID ACC_ADDR CITY_ID
1 1 Three bedroom bungalow near theme park 500 3 1
2 1 Two bedroom bungalow next to disney house 350 2 1
3 1 One bedroom bungalow with lake view 250 2 2
4 2 One bedroom chalet near the lake 150 1 2
5 2 Four bedroom chalet near the tree house 600 4 3
Reservation
RESV_ID EMP_ID BOOKING_CUS_ID RESV_DATE HOLIDAY_S HOLIDAY_E IN_FLIGHT_ID OUT_FLIGHT_ID IN_FLIGHT_SEATS_NO OUT_FLIGHT_SEATS_NO ACC_ID SUBTOTAL
1 338 1 16-FEB-12 18-MAR-12 20-APR-12 1 11 2 2 2
2 335 3 10-JAN-12 20-MAR-12 22-APR-12 2 12 2 2 4
3 338 5 05-MAR-12 25-MAR-12 26-APR-12 3 13 2 2 6
4 328 7 02-JAN-12 25-MAR-12 25-APR-12 4 14 2 2 7
5 311 9 20-JAN-12 26-MAR-12 21-APR-12 5 15 2 2
6 317 11 07-JAN-12 27-MAR-12 22-APR-12 6 16 2 2
7 344 13 29-FEB-12 15-MAR-12 12-APR-12 7 17 2 2
8 326 15 11-JAN-12 18-MAR-12 12-APR-14 8 18 2 2
9 329 17 16-JAN-12 19-MAR-12 17-APR-12 25
10 323 19 18-FEB-12 20-MAR-12 21-APR-12 19
Okay I managed to yield the results that i wanted
SELECT HR.RESV_ID, F_IN.FLI_ID, F_IN.FLI_PRICE, F_OUT.FLI_ID, F_OUT.FLI_PRICE, AC.ACC_ID, AC.ACC_PRICEPN, NVL(F_IN.FLI_PRICE,0)+NVL(F_OUT.FLI_PRICE,0)+NVL(AC.ACC_PRICEPN,0) AS TOTAL
FROM HOLIDAY_RESERVATION HR
LEFT JOIN FLIGHT F_IN ON HR.IN_FLIGHT_ID = F_IN.FLI_ID
LEFT JOIN FLIGHT F_OUT ON HR.OUT_FLIGHT_ID = F_OUT.FLI_ID
LEFT JOIN ACCOMMODATION AC ON HR.ACC_ID = AC.ACC_ID
ORDER BY HR.RESV_ID;
YIELDS
RESV_ID FLI_ID FLI_PRICE FLI_ID FLI_PRICE ACC_ID ACC_PRICEPN TOTAL
---------- ---------- ---------- ---------- ---------- ---------- ----------- ----------
1 1 500 11 555 2 350 1405
2 2 150 12 253 4 150 553
3 3 300 13 345 6 450 1095
4 4 450 14 343 7 650 1443
5 5 345 15 242 587
6 6 460 16 460 920
7 7 250 17 250 500
8 8 550 18 550 1100
9 25 250 250
10 19 450 450
And the following statement is to update the reservation table.
Thanks to Leigh Riffel from DBA stackxchange for the following code
UPDATE HOLIDAY_RESERVATION R SET SUBTOTAL =
NVL((SELECT F.FLI_PRICE FROM FLIGHT F WHERE F.FLI_ID = R.IN_FLIGHT_ID), 0) +
NVL((SELECT F.FLI_PRICE FROM FLIGHT F WHERE F.FLI_ID = R.OUT_FLIGHT_ID), 0) +
NVL((SELECT AC.ACC_PRICEPN FROM ACCOMMODATION AC WHERE AC.ACC_ID = R.ACC_ID), 0);
Now the subtotal is populated with the values obtained from the sum performed above >>
RESV_ID EMP_ID BOOKING_CUS_ID RESV_DATE HOLIDAY_S HOLIDAY_E IN_FLIGHT_ID OUT_FLIGHT_ID IN_FLIGHT_SEATS_NO OUT_FLIGHT_SEATS_NO ACC_ID SUBTOTAL
---------- ---------- -------------- --------- --------- --------- ------------ ------------- ------------------ ------------------- ---------- ----------
1 338 1 16-FEB-12 18-MAR-12 20-APR-12 1 11 2 2 2 1405
2 335 3 10-JAN-12 20-MAR-12 22-APR-12 2 12 2 2 4 553
3 338 5 05-MAR-12 25-MAR-12 26-APR-12 3 13 2 2 6 1095
4 328 7 02-JAN-12 25-MAR-12 25-APR-12 4 14 2 2 7 1443
5 311 9 20-JAN-12 26-MAR-12 21-APR-12 5 15 2 2 587
6 317 11 07-JAN-12 27-MAR-12 22-APR-12 6 16 2 2 920
7 344 13 29-FEB-12 15-MAR-12 12-APR-12 7 17 2 2 500
8 326 15 11-JAN-12 18-MAR-12 12-APR-14 8 18 2 2 1100
9 329 17 16-JAN-12 19-MAR-12 17-APR-12 25 250
10 323 19 18-FEB-12 20-MAR-12 21-APR-12 19 450
Subsequently the code was added to a trigger (which was the original intention)
CREATE OR REPLACE TRIGGER HR_SUBTOTAL
BEFORE INSERT OR UPDATE ON HOLIDAY_RESERVATION
FOR EACH ROW
BEGIN
SELECT
NVL((SELECT F.Fli_Price FROM Flight F WHERE F.Fli_ID = :new.In_Flight_ID), 0) +
NVL((SELECT F.Fli_Price FROM Flight F WHERE F.Fli_ID = :new.Out_Flight_ID), 0) +
NVL((SELECT AC.Acc_PricePn FROM Accomodation AC WHERE AC.Acc_ID = :new.Acc_ID), 0)
INTO :new.Subtotal
FROM dual;
END;
/
For the SUM, assuming you want to treat NULL values as 0, you'd just need to do an NVL on the numbers
NVL( DEPART_FLIGHT_PRICE, 0 ) +
NVL( RETURN_FLIGHT_PRICE, 0 ) +
NVL( ACCOMMODATION_PRICE, 0 )
As for the UPDATE, it sounds like you just need a correlated UPDATE statement.
UPDATE reservation r
SET subtotal = (SELECT (SELECT NVL( DEPART_FLIGHT_PRICE, 0 ) +
NVL( RETURN_FLIGHT_PRICE, 0 ) +
NVL( ACCOMMODATION_PRICE, 0 )
FROM (SELECT RESV_ID,
BOOKING_CUS_ID,
ACC_ID,
(SELECT F.FLI_PRICE
FROM FLIGHT F
WHERE F.FLI_ID = R.IN_FLIGHT_ID) AS DEPART_FLIGHT_PRICE,
(SELECT F1.FLI_PRICE
FROM FLIGHT F1
WHERE F1.FLI_ID = R.OUT_FLIGHT_ID) AS RETURN_FLIGHT_PRICE,
(SELECT AC.ACC_PRICEPN
FROM ACCOMMODATION AC
WHERE AC.ACC_ID = R.ACC_ID) AS ACCOMMODATION_PRICE
FROM dual));
You are asking:
How do I sum up the price fields, as you can see some of them can have nulls.
DEPART_FLIGHT_PRICE RETURN_FLIGHT_PRICE ACCOMMODATION_PRICE
Just enclose them in NVL function as follows:
NVL(DEPART_FLIGHT_PRICE, 0)
and then sum them up.
For the second part, what you need is a MERGE statement. A good example is at http://www.oracle-developer.net/display.php?id=203