SQL oracle - Delete Duplicate Records and update records in other table - sql

Requirement - Delete Duplicate records e.g. from 2 tables and update the records in the other tables.
Input
Table1 Dim_Ctry
PK_Key1 Country
100 Argentina
200 ARGENTINA
300 India
400 INDIA
Table2 Dim_Geo
PK_Key2 Geo
500 Globe
600 GLOBE
700 Market
800 MARKET
900 Unique
Table Fact1
PK_Key15 FK_KEY1 FK_KEY2
1 100 500
2 200 600
3 300 800
4 400 900
Table Fact2
PK_Key16 FK_KEY1 FK_KEY2
5 100 500
6 200 600
7 200 700
8 300 800
output
Table1 Dim_Ctry
PK_Key1 Country
100 Argentina
300 India
Table2 Dim_Geo
PK_Key2 Geo
500 Globe
700 Market
900 Unique
Table Fact1
PK_Key15 FK_KEY1 FK_KEY2
1 100 500
2 100 500
3 300 800
4 300 800
Table Fact2
PK_Key16 FK_KEY1 FK_KEY2 comment
5 100 500
6 100 500
7 100 700
7 300 800
8 1000 2000 no record in dim table just retain

You will need several steps.
Step 1 update related tables
Update all FK_KEY to the min value.
UPDATE Fact1 f1
SET
FK_KEY1 = (SELECT MIN(PK_Key1)
FROM Dim_Ctry dc1
WHERE UPPER(dc1.Country) = (SELECT UPPER(dc2.Country)
FROM Dim_Ctry dc2
WHERE dc2.PK_Key1 = f1.FK_KEY1)
),
FK_KEY2 = (SELECT MIN(PK_Key2)
FROM Dim_Geo dg1
WHERE UPPER(dg1.Geo) = (SELECT UPPER(dg2.Geo)
FROM Dim_Geo dg2
WHERE dg2.PK_Key2 = f1.FK_KEY2)
);
Step 2 delete duplicated
This will delete all duplicated and keep the one with smaller id
DELETE FROM Dim_Ctry dc1
WHERE EXISTS (SELECT PK_Key1
FROM Dim_Ctry dc2
WHERE dc1.PK_Key1 > dc2.PK_Key1
and UPPER(dc1.Country) = UPPER(dc2.Country)
Step 3 update the text
You should update to lower or upper to standard format.
UPDATE Dim_Ctry
SET Country = UPPER(Country)
debug query
SELECT f1.PK_Key15, f1.FK_KEY1, f1.FK_KEY2,
(SELECT UPPER(dc2.Country)
FROM Dim_Ctry dc2
WHERE dc2.PK_Key1 = f1.FK_KEY1
) as CurrentName,
(SELECT MIN(PK_Key1)
FROM Dim_Ctry dc1
WHERE UPPER(dc1.Country) = (SELECT UPPER(dc2.Country) FROM Dim_Ctry dc2 WHERE dc2.PK_Key1 = f1.FK_KEY1) ) as minKey
FROM Fact1 f1

Related

Cumulative over table rows with condition Oracle PL/SQL

I have two tables:
Employees:
employee_id field max_amount
3 a 3000
4 a 3000
1 a 1600
2 a 500
4 b 4000
2 b 4000
3 b 1700
ordered by employee, field, amount desc.
Amounts (pol, premia,field):
pol premia field **assign_to_employee**
11 900 a 3
44 1000 a 3
55 1400 a 4
77 500 a 3
88 1300 a 1
22 800 b 4
33 3900 b 2
66 1300 b 4
Assign Stats Table:
employee_id field max_amount true_amount remain
3 a 3000 2400 600
4 a 3000 1400 1600
1 a 1600 1300 300
2 a 500 0 500
4 b 4000 2100 1900
2 b 4000 3900 100
3 b 1700 0 1700
The output : assign_to_employee field (merged to amounts table).
Algoritem wise : The method is to assign pol's to employees until the premia needs to be added to the cumulative_sum is bigger then the max amount per employee listed in the employees table. You always start with the employess with most max amount until you cannot add any other pols to the employee.
I start with the employees with the grater max_amount per field.
I keep doing this until no pols remains to be assign.
Can you help me solve this?
Thank you.

sum tabel based on certain content

select
om.orderno,
od.product,
od.preorderqty,
(od.preorderqty * od.nto) as preordernet
from OrderMaster om
join OrderDetail od on od.orderid = om.id
and ((od.prodcode like '100-%') or (od.prodcode like '200-%'))
order by om.orderno,sod.prodcode
Current result:
ORDERNO PRODUCT PREORDERQTY PREORDERNET
1000 100-A 2 200
1000 100-B 2 300
1000 100-C 1 450
2000 100-A 3 300
2000 100-B 1 150
2000 200-A 2 900
3000 200-A 1 450
I would need help getting a script that:
Sums the orders based on specific content
Orders can contain products beginning with 300- etc.
Expected result:
ORDERNO PRODUCT PREORDERQTY PREORDERNET ORDERNET
1000 100-A 2 200 950
1000 100-B 2 300 950
1000 100-C 1 450 950
2000 100-A 3 300 1350
2000 100-B 1 150 1350
2000 200-A 2 900 1350
3000 200-A 1 450 450
As I understood from the expected output ,use sum as window function to get it,
select om.orderno
,od.product
,od.preorderqty
,(od.preorderqty * od.nto) as preordernet
,sum(od.preorderqty * od.nto) over (partition by om.orderno) as ordernet
from OrderMaster om
join OrderDetail od
on od.orderid = om.id
and ((od.prodcode like '100-%')
or (od.prodcode like '200-%'))
order by om.orderno,sod.prodcode

adding two columns in two tables having multiple layers

I am having two tables here from which I needed to add two columns.
table 1 table 2
1 ram 100 null 1 ram 100 1000
2 ram 200 1000 2 ram 200 null
3 ram 100 2000 3 ram 100 3000
4 ram 100 3000 4 ram 100 4000
5 ram 100 null 5 ram 100 5000
1 rahim 100 5000 1 rahim 100 null
2 ram 200 6000 2 ram 200 7000
3 ram 200 null 3 ram 200 8000
4 ram 200 null 4 ram 200 9000
5 rahim 100 9000 5 rahim 100 null
1 robert 100 10000 1 robert 100 11000
2 rahim 200 11000 2 rahim 200 12000
3 ram 300 12000 3 ram 300 null
4 rahim 400 13000 4 rahim 400 14000
5 robert 100 14000 5 robert 100 15000
result should be in the form:
1 ram 100 1000
2 ram 200 -1000
3 ram 100 1000
4 ram 100 1000
5 ram 100 5000
1 rahim 100 -5000
2 ram 200 1000
3 ram 200 8000
4 ram 200 9000
5 rahim 100 -9000
1 robert 100 1000
2 rahim 200 1000
3 ram 300 -12000
4 rahim 400 1000
5 robert 100 1000
You can use join with coalesce to remove the null values:
select t1.id, t1.somefield, t1.someint,
coalesce(t2.someint2,0)-coalesce(t1.someint2,0)
from table1 t1
join table2 t2 on t1.id = t2.id
and t1.somefield = t2.somefield
and t1.someint = t2.someint
SQL Fiddle Demo
Based on your input data, this joins on the first 3 columns. Not completely sure this is what you want, but should get you going in the correct direction.
I think try subtract table2.col4 with table1.col4.
SELECT a.col1,
a.col2,
a.col3,
NVL(a.col4, 0) - NVL(b.col4, 0) SUB
FROM table1 A
JOIN table2 B
ON A.col1 = b.col1
AND a.col2 = b.col2

SQL join two table together

I have the following tables:
table1
a b
1 100
2 200
3 300
4 400
table2
c b
55 100
55 200
56 300
I want to get the following output:
55 100 1
55 200 2
55 300 -
55 400 -
56 100 -
56 200 -
56 300 3
56 400 -
I tried the following:
SELECT *
FROM table1
full JOIN table2
output:
a b c a
1 100 55 100
1 100 55 200
1 100 55 100
1 100 55 200
2 300 56 300
....
also I tried:
SELECT *
FROM table1
join table2 on table1.b = table2.b
union
SELECT *
FROM table2
join table1 on table1.b = table2.b
the output:
1 100 55 100
1 200 55 200
3 300 56 300
Is this possible in microsoft SQL 2012? and how
I'm not completely sure I understand your expected outcome, but it sounds like you're looking for a FULL OUTER JOIN.
SELECT table1.a, COALESCE(table1.b, table2.b), table2.c
FROM table1
FULL OUTER JOIN table2 ON table1.b = table2.b
This will get the fields from table1 and, if any exist, map them to those from table2.
Given your example, it will return the following table.
A B C
1 100 55
2 200 55
3 300 56
4 400 (null)
I know that isn't the same as the expected result you gave, but this will correlate the data that actually exists.
I'm requesting clarification in a comment and will revise this as necessary.

How to assign the Parent Group IDs to each record of a hierarchical table in Oracle 11g?

Based on the following sample hierarchical data that exists within the TECH_VALUES table, how can I create a view, say TECH_VALUES_VW that will take this same data but have an additional column, namely GROUP_ID_PARENT that will show the group id where the parent group id is 0 against the row that child belongs to, see new column data sample:
ID GROUP_ID LINK_ID PARENT_GROUP_ID TECH_TYPE GROUP_ID_PARENT
------- ------------- ------------ -------------------- ---------- ---------------
1 100 LETTER_A 0 100
2 200 LETTER_B 0 200
3 300 LETTER_C 0 300
4 400 LETTER_A1 100 A 100
5 500 LETTER_A2 100 A 100
6 600 LETTER_A3 100 A 100
7 700 LETTER_AA1 400 B 100
8 800 LETTER_AAA1 700 C 100
9 900 LETTER_B2 200 B 200
10 1000 LETTER_BB5 900 B 200
12 1200 LETTER_CC1 300 C 300
13 1300 LETTER_CC2 300 C 300
14 1400 LETTER_CC3 300 A 300
15 1500 LETTER_CCC5 1400 A 300
16 1600 LETTER_CCC6 1500 C 300
17 1700 LETTER_BBB8 900 B 200
18 1800 LETTER_B 0 1800
19 1900 LETTER_B2 1800 B 1800
20 2000 LETTER_BB5 1900 B 1800
21 2100 LETTER_BBB8 1900 B 1800
So based on the above, I want to take the table definition:
Table Name: TECH_VALUES:
ID,
GROUP_ID,
LINK_ID
PARENT_GROUP_ID,
TECH_TYPE
and create a new view
View Name: TECH_VALUES_VW:
ID,
GROUP_ID,
LINK_ID
PARENT_GROUP_ID,
TECH_TYPE,
GROUP_ID_PARENT
based on the above sample data from the TECH_VALUES table.
I am looking to create a new query to build this new view which will only use the GROUP_IDs for the PARENT_GROUP_IDs that are 0 for each row.
Updated
Just to make things a whole lot clearer of exactly what I am after is if I take out only the records where the PARENT_GROUP_ID is 0 within the TECH_VALUES table, i.e.
ID GROUP_ID LINK_ID PARENT_GROUP_ID
------- ------------- ------------ --------------------
1 100 LETTER_A 0
2 200 LETTER_B 0
3 300 LETTER_C 0
18 1800 LETTER_B 0
Using just the GROUP_ID values for these 4 records, assign this GROUP_ID to all of the children records for each of these parent link ids as a new column in the TECH_VALUES_VW as well as to the original link ids (where PARENT_GROUP_ID is 0) as shown in the sample data set above.
If I understood your question correctly, then this might be what you're after:
CREATE OR REPLACE VIEW tech_values_vw
AS
SELECT TV.*,
CASE WHEN LEVEL = 1 THEN group_id ELSE connect_by_root(group_id) END AS group_id_parent
FROM tech_values TV
START WITH parent_group_id = 0
CONNECT BY PRIOR group_id = parent_group_id
;