Row value inconsistency - sql

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

Related

Presto SQL - product combination matrix to find substitutes

I have this input (product list table and its buyers)
product_id customer_id
p1 c1
p2 c1
p2 c2
p3 c1
p3 c2
p4 c2
and need to get this dynamic matrix output in SQL, Presto.
p1 p2 p3 p4
p1 2 1 0
p2 2 1
p3 1
p4
any thoughts are very appreciated

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.

Create dynamic binary columns in sql query

I'm using presto db
I have two tables, one looks like:
table 1:
item count
p1 20
p2 10
p3 5
p4 4
p5 2
and table 2:
person lic
c1 p2
c1 p1
c2 p3
c2 p4
c2 p2
c3 p1
c4 p2
I want to return a table that looks like:
person p1 p2 p3 p4 p5
c1 1 1 0 0 0
c2 0 1 1 1 0
c3 1 0 0 0 0
c4 0 1 0 0 0
c5 0 0 0 0 0
It looks like a pivot would do, but im not sure how to account for missing values in the column and get them to be '0' in the final table
The output schema for a SQL query must be fixed. Thus, if you want a column p1 to appear in the output, it has to be listed explicitly in the query.
I'm not sure how table1 is related to the output, but you can do a pivot like this:
SELECT person
, count_if(lic = 'p1') p1
, count_if(lic = 'p2') p2
...
FROM table2
GROUP BY person
The query needs to list each p column. Depending on your application, you might be able to generate the query programmatically by first running a query to get the unique values of p.

Take the max value of a column in a sql table

I have this query:
SELECT DISTINCT S.PRODOTTO, D.CODPROD, D.IDPROD
FROM D_PROD D, APP_SALES S
WHERE D.CODPROD = S.PRODOTTO
The result is:
PRODOTTO CODPROD IDPROD
P2 P2 2
P1 P1 1
P3 P3 4
P3 P3 3
Now I would the result was
PRODOTTO CODPROD IDPROD
P2 P2 2
P1 P1 1
P3 P3 4
with the product P3 that take the max idprod it has encountered.
How can I say to the query to take the max value if there are more rows of one product?
I want the max idprod.
SELECT DISTINCT S.PRODOTTO, D.CODPROD, MAX(D.IDPROD)
FROM D_PROD D, APP_SALES S
WHERE D.CODPROD = S.PRODOTTO
GROUP BY S.PRODOTTO, D.CODPROD

Complex insert thru Stored Procedure

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.