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

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.

Related

Need YTD and MTD calculations in SQL

Date Amt ytd mtd
01-Jan-21 1 2 2
01-Jan-21 1 2 2
02-Jan-21 1 3 3
03-Jan-21 1 4 4
01-Feb-21 1 5 1
02-Feb-21 1 6 2
03-Feb-21 1 7 3
04-Feb-21 1 8 4
05-Feb-21 1 9 5
01-Mar-21 1 10 1
02-Mar-21 1 11 2
03-Mar-21 1 12 3
04-Mar-21 1 13 4
01-Apr-21 1 14 1
02-Apr-21 1 15 2
03-Apr-21 1 16 3
01-May-21 1 17 1
02-May-21 1 18 2
03-May-21 1 19 3
04-May-21 1 20 4
05-May-21 1 21 5
06-May-21 1 22 6
I have the first two columns (Date, Amt) and i need the YTD and MTD columns in MS SQL so that i can show the above table.
Seems like a rolling COUNT OVER was used to calculate the ytd & mtd in the Oracle source.
(Personally, I would prefere RANK or DENSE_RANK)
And since Oracle datestamps can be casted to a DATE as-is.
SELECT [Date], Amt
, ytd = COUNT(*) OVER (ORDER BY CAST([Date] AS DATE))
, mtd = COUNT(*) OVER (PARTITION BY EOMONTH(CAST([Date] AS DATE)) ORDER BY CAST([Date] AS DATE))
FROM your_table
ORDER BY CAST([Date] AS DATE)
Date
Amt
ytd
mtd
01-Jan-21
1
2
2
01-Jan-21
1
2
2
02-Jan-21
1
3
3
03-Jan-21
1
4
4
01-Feb-21
1
5
1
02-Feb-21
1
6
2
03-Feb-21
1
7
3
04-Feb-21
1
8
4
05-Feb-21
1
9
5
db<>fiddle here

Distinguish the first rows where a given column's value changes in a grouped result

I want to create a select query in SQL Server where I group the rows by a column (BaseId) and also order them by Status, RTime and Version. I want to add a column "isFirst" that has the value 1 if the BaseId value is the first in the group, and 0 if it's not.
My sample table:
Table name: Head
Id BaseId Name RTime Status Version
2 2 abc 04-12 12:34 1 1
3 3 xyz 04-12 13:10 9 1
4 2 abc 04-13 14:25 0 2
5 3 xyz 04-14 12:34 0 2
6 3 xyz 04-14 13:10 9 3
7 3 xyz 04-16 14:25 1 4
8 2 abc 04-16 17:40 1 3
9 9 sql 04-17 02:23 9 1
10 9 sql 04-17 07:31 0 2
Expected result:
isFirst Id BaseId Name RTime Status Version
1 10 9 sql 04-17 07:31 0 2
0 9 9 sql 04-17 02:23 9 1
1 5 3 xyz 04-14 12:34 0 2
0 7 3 xyz 04-16 14:25 1 4
0 6 3 xyz 04-14 13:10 9 3
0 3 3 xyz 04-12 13:10 9 1
1 4 2 abc 04-13 14:25 0 2
0 8 2 abc 04-16 17:40 1 3
0 2 2 abc 04-12 12:34 1 1
My query now looks like this:
SELECT *
FROM Head
ORDER BY BaseId desc, Status, RTime desc, Version desc
I think I should use CASE to create the isFirst column, but I've had no luck so far. Anyone could help me?
You can use row_number() and a case expression:
select
case when row_number() over(
partition by BaseId
order by Status, RTime desc, Version desc
) = 1
then 1
else 0
end isFirst,
h.*
from head h
order by BaseId desc, Status, RTime desc, Version desc

Need to Roll Parent Quantities to Calculate Total Quantity

Thanks in advance for any assistance you can provide. I have spent hours on this with no luck.
I'm working with an indented bill of material table which has an end part id, a sequence number, a level and a quantity. The goal is to determine the total cumulative quantity of each row on this table.
What makes this difficult is that to determine the total quantity, the child quantity needs to be multiplied by it's parent quantity. The parent quantity of that parent needs to be multiplied by it's parent quantity and so on.
For example, a level 3 part has a component quantity of 5. It's parent the level 2 part has a component quantity of 2. It's parent the level 1 part has a component quantity of 3. This means the level 3 part total quantity is 30 (3 X 2 X 5).
With the assistance of SO (specifically #KKK) the parent quantity was able to be calculated in the below query. After this was resolved I realized I now need two additional columns, one that shows the Rolled/Cumulative quantities of the parent rows and one that shows the total quantity of the child.
The attached screenshot has the two columns that need to be added highlighted in yellow. Here is the current SQL (using Oracle 10.2) for the columns that are not in yellow:
select
end_part_id, sort_seq_no, indented_lvl, comp_qty,
(select distinct first_value(a.comp_qty) over (order by a.sort_seq_no desc, TRIM(a.indented_lvl) desc)
from
report_table a
where
a.end_part_id = b.end_part_id
and a.sort_seq_no < b.sort_seq_no
and TRIM(a.indented_lvl) < TRIM(b.indented_lvl)) as "PARENT_QTY"
from report_table b
Expected Results
END_PART_ID SORT_SEQ_NO INDENTED_LVL COMP_QTY PARENT_QTY ROLLED_PARENT QTY TOTAL_QTY
PARTX 1 1 2 1 1 2
PARTX 2 2 5 2 2 10
PARTX 3 3 2 5 10 20
PARTX 4 4 1 2 20 20
PARTX 5 5 1 1 20 20
PARTX 6 6 1 1 20 20
PARTX 7 5 4 1 20 80
PARTX 8 6 1 4 80 80
PARTX 9 2 7 2 2 14
PARTX 10 3 2 7 14 28
PARTX 11 3 2 7 14 28
PARTX 12 4 1 2 28 28
PARTX 13 4 1 2 28 28
PARTX 14 3 8 7 14 112
PARTX 15 1 1 1 1 1
PARTX 16 2 7 1 1 7
PARTX 17 3 2 7 7 14
PARTX 18 3 2 7 7 14
PARTX 19 4 1 2 14 14
PARTX 20 4 1 2 14 14

Splitting Column Headers and Duplicating Row Values in Pandas Dataframe

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

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