Complex insert thru Stored Procedure - sql

I have 1 table with row data (No Primary Ky). and Another with Primary Key.
In row data table, i have multiple records on 3 perameters. And other 10 Field with same value in all the records on these 3 pereameters.
Eg.
aa bb cc dd ee ff gg hh ii p1 p2 p3 V1 V2 V3 V4
a1 b1 c1 d1 e1 f1 g1 h1 i1 zz 123 03-05-2009 5 2 3 4
a1 b1 c1 d1 e1 f1 g1 h1 i1 zz 123 03-05-2009 10 1 4 4
I want to insert in my table is like
aa bb cc dd ee ff gg hh ii p1 p2 p3 V1 V2 V3 V4
a1 b1 c1 d1 e1 f1 g1 h1 i1 zz 123 03-05-2009 15 3 7 8
Only one record group by column p1,p2,p3...
Can any one suggest me how to write SP For this??
I have defined one cursor with columns p1,p2,p3.
First i m checking that These type of record exists in master or not? as in my master table Primary key is based on these perameters.
Then i have written query with gorup by clause...??
But is it right way of doing it???
Please guide..
Thanks In Advance..

Oy - no cursors here, friend. None needed. Try this:
INSERT MyDetailTable (aa, bb, cc, dd, ee, ff, gg, hh, ii, p1, p2, p3, V1, V2, V3, V4)
SELECT d.aa, d.bb, d.cc, d.dd, d.ee, d.ff, d.gg, d.hh, d.ii, d.p1, d.p2, d.p3, SUM(d.V1), SUM(d.V2), SUM(d.V3), SUM(d.V4)
FROM MyDetailTable d
JOIN MyMasterTable m ON d.p1 = m.p1
AND d.p2 = m.p2
AND d.p3 = m.p3
GROUP BY d.aa, d.bb, d.cc, d.dd, d.ee, d.ff, d.gg, d.hh, d.ii, d.p1, d.p2, d.p3
The JOIN only exists to verify that the PK exists in the master table (although you should be using a foreign key constraint to ensure that this is the case - so you don't need to check that a master record exists in every statement you run against the detail table).
Grouping does just that - groups by the "common" fields for each row. Instead of grouping by aa, bb, cc.....p1, p2, p3, you could just group by p1, p2, p3 and use MAX(aa), MAX(bb),... if you prefer - it's really up to you.

Related

Custom Sort on Group By Column SSRS / SQL

I have a sample data as below.
Key KeyName CustomerName CID Role
1 K1 Ram C1 Main
1 K1 Laxman C5 Child
2 K2 Shyam C2 Main
3 K3 Ram C1 Main
4 K4 Shyam Bothe C2 Main
5 K5 Berry C3 Child
6 K6 Berry Ping C3 Main
Here the same customer exist in multiple keys. I want to sort the duplicate customers in the order of their keys as below.
Key KeyName CustomerName CID Role
1 K1 Ram C1 Main
1 K1 Laxman C5 Child
3 K3 Ram C1 Main
2 K2 Shyam C2 Main
4 K4 Shyam Bothe C2 Main
5 K5 Berry C3 Child
6 K6 Berry Ping C3 Main
SELECT Key, KeyName, CustomerName, CID, Role
from table
order by CID, KeyName asc;

how to append two tables with different columns in aws athena

I want help in writing a query which appends two tables with some similar columns and other columns too.
For example if I have 2 tables,
Table 1:
name age place
n1 a1 p1
n2 a2 p2
n3 a3 p3
Table 2:
name place country
n4 p4 c4
n5 p5 c5
n6 p6 c6
I want to append these two tables to get
Table 3:
name age place country
n1 a1 p1 NULL
n2 a2 p2 NULL
n3 a3 p3 NULL
n4 NULL p4 c4
n5 NULL p5 c5
n6 NULL p6 c6
Is this possible?
Thanks
You can use a UNION query with placeholders for missing columns on each table:
SELECT name, age, place, null AS country FROM table1
UNION ALL
SELECT name, null AS age, place, country FROM table2
ORDER BY name;
Notice that I have created two columns so that each result set has the same set of columns.

Oracle SQL -- how to delete partial duplicates with a preference

Could you please help me in deleting duplicates (partial) from table? I have a table containing 5 columns. And in this table I have duplicates -- but only 4 columns are the same and one of the columns (field5) is different. That is:
F1 F2 F3 F4 F5
A1 A2 A3 A4 103
A1 A2 A3 A4 3
So, for a duplicate, 4 columns/fields are the same, except the 5th one. And I want to delete the row containing number "103", that's, a higher number. How can I achieve this?
If this was a normal duplicate, I would just use max(rowid) and remove that row. But now this could delete the row containing lower number instead of the higher number.
One method that I can think of is creating a new table containing rows which are duplicate and Field5 has a higher number from this table. Then deleting rows from original table by comparing it to this new table. But that seems not so good solution to me -- especially if the original table is big, this might take long time.
Any help would be much appreciated. Thank you.
Idea is to keep a record for each combinations of F1,F2,F3,F4 and delete the rest.
Try this:
DELETE FROM TABLE_NAME WHERE ROWID IN
(SELECT ROWID FROM
(SELECT ROWID, row_number() OVER(PARTITION BY F1,F2,F3,F4 ORDER BY F5) RN
FROM TABLE_NAME)
WHERE RN<>1);
How about this?
SQL> select * from test order by f1, f5;
F1 F2 F3 F4 F5
-- -- -- -- ----------
a1 a2 a3 a4 3
a1 a2 a3 a4 50 --> delete
a1 a2 a3 a4 103 --> delete
b1 b2 b3 b4 2
b1 b2 b3 b4 200 --> delete
c1 c2 c3 c4 1
6 rows selected.
SQL> delete from test t
2 where rowid not in (select rowid
3 from test t1
4 where t1.f1 = t.f1
5 and t1.f2 = t.f2
6 and t1.f3 = t.f3
7 and t1.f4 = t.f4
8 and t1.f5 =
9 (select min (t2.f5)
10 from test t2
11 where t2.f1 = t.f1
12 and t2.f2 = t.f2
13 and t2.f3 = t.f3
14 and t2.f4 = t.f4));
3 rows deleted.
SQL> select * from test order by f1, f5;
F1 F2 F3 F4 F5
-- -- -- -- ----------
a1 a2 a3 a4 3
b1 b2 b3 b4 2
c1 c2 c3 c4 1
SQL>
I normally just do this:
delete demo
where rowid in
( select lead(rowid) over (partition by f1, f2, f3, f4 order by f5) as next_rowid
from demo );
That is, delete every "next" row in order of f5 within its (f1, f2, f3, f4) group.

Using same database table with different alias to retrieve data

Here what I am trying to do is to get the values for P1,P2,P3 that should comes from A3,
this works well for two tables but not for three...
SELECT x.A1,x.A3,x.A4,A5,A6, x.A2 as P1,y.A2 as P2,z.A2 as P3
FROM Contact x,Contact y,Contact z
WHERE (x.id = y.id) AND (y.id = z.id) AND
(x.A3 ='pre-sale') AND (y.A3= pos-sale') AND(z.A3='current-sale')
ORDER by x.A4 DESC
For example
the CONTACT table will look like this with some expected results for P1,P2, P3
A1 A2 A3 A4 A5 A6 P1 P2 P3
----------------------------------------------------
1 22 pre-sale 9 kk 8 22 31 2
2 31 pos-sale 4 yy 6 44 61 11
3 2 current-sale 1 hh 2 null null null
4 44 pre-sale 2 kk 8
5 61 pos-sale 1 yy 6
6 11 current-sale 1 hh 2
For P1, P2 using twice same table works well, adding the third table the values
for P1, P2 are the same and for P3 all null
I suspect that what you are trying to do might best be done with conditional aggregation. It is a bit hard to tell what you are really trying to accomplish, because not all the columns are aliased. Here is an example
SELECT c.id,
max(case when c.A3 = 'pre-sale' then A4 end) as PreSale_A4,
max(case when c.A3 = 'pos-sale' then A2 end) as PosSale_A2,
max(case when c.A3 = 'current-sale' then A4 end) as CurrentSale_A2
FROM Contact c
group by c.id
order by PreSale_A4 desc;
Your original query has some fundamental problems. For instance, you are using implicit joins via the where clause, which are always inner joins. The solution to your problem might be using outer joins instead. Conditional aggregation probably solves the problem, though.

Row value inconsistency

Scenario -
We have pack items, which is defined as a composite of one or more items. A complex pack is a one that has more than one component items. Each component item of a complex pack item should be linked to equal number of locations.
For example:
Pack P1 has component C1, C2, and C3. Each item C1,C2 and C3 is ranged to 10 locations 1,2....10, such that C1-1,C1-2,...,C1-10,C2-1,C2-2,...,C2-10,and C3-1,C3-2,...,C3-10 exists. In such case the pack item P1 also gets associated to locations 1 through 10, as P1-1,P1-2,...,P1-10.
The table PACK_BREAKOUT contains the Pack component mapping and the table ITEM_LOCATION contains the items to location association. Both Pack and Component are considered as "items" and would exist in ITEM_LOCATION.
Ideally, for the a scenario like above the below record-set would be valid
PACK_NO ITEM NO_OF_LOC
-------- ------ -------------
P1 C1 10
P1 C2 10
P1 C3 10
I have the query below that returns result like above for all such pack items.
select c.pack_no,c.item,count(a.loc )
from item_location a, pack_breakout c
where c.item=a.item
group by c.pack_no,c.item
order by 1,2;
However, there are some discrepant results like pack no. P2 , P4, and P5 below where the components are not associated with equal number of locations.
PACK_NO ITEM NO_OF_LOC
-------- ------ -------------
P1 C1 10
P1 C2 10
P1 C3 10
P2 C1 11
P2 C2 5
P2 C3 9
P2 C4 11
P3 C1 21
P3 C2 21
P3 C3 21
P3 C4 21
P3 C5 21
P4 C1 10
P4 C2 15
P5 C1 10
P5 C2 9
P5 C3 10
P5 C4 10
Note that a pack can have n-number of components (as you can see P1, P2, P3, P4, and P5 have different number of components).
I would like to get only the packs whose component locations are not all consistent. So the desired result set would be-
PACK_NO ITEM NO_OF_LOC
-------- ------ -------------
P2 C1 11
P2 C2 5
P2 C3 9
P2 C4 11
P4 C1 10
P4 C2 15
P5 C1 10
P5 C2 9
P5 C3 10
P5 C4 10
Note that even if one component does not match no. of locations as the other components within the pack, the entire pack must be considered inconsistent (like P5).
You want to use another group by with a having clause:
select pack_no
from (select c.pack_no, c.item, count(a.loc ) as numlocs
from item_location a join
pack_breakout c
on c.item=a.item
group by c.pack_no, c.item
) p
group by pack_no
having MIN(numlocs) <> MAX(numlocs)
This returns the packs.
If you want the details of the numbers, then use the analytic functions for the calculation:
select pi.*
from (select pi.*, min(numlocs) over (partition by pack_no) as minnumlocs,
max(numlocs) over (partition by packno) as maxnumlocs
from (select c.pack_no, c.item, count(a.loc ) as numlocs
from item_location a join
pack_breakout c
on c.item=a.item
group by c.pack_no, c.item
) pi
) pi
where minnumlocs <> maxnumlocs