How to assign aliases to multiple select statements - oracle

My issue is the right join is not working, I am guessing due to aliases used.
I have commented the lines using -- to indicate the lines that most probably are causing the issue. If I run my Cross Join part of the code separately it works fine.
If I add the cross join as show below, and then do a right join with the table final_leg a I am receiving an error saying 'relation "k" does not exist'.
k is the alias I am using in the last select statement to call the CROSS join part of the table.
WITH final_leg AS(
SELECT y.*
FROM
(
SELECT
y.shipment_id,
y.route_id,
max(leg_sequence_id) max_leg_sequence_id
FROM posimorders.sc_execution_eu.o_detailed_routes_v2 y
group by
1,2
) AS x
INNER JOIN posimorders.sc_execution_eu.o_detailed_routes_v2 y
on x.route_id = y.route_id and x.shipment_id = y.shipment_id and y.leg_sequence_id = x.max_leg_sequence_id
),
dest_leg AS(
SELECT y.*
FROM
(
SELECT
y.shipment_id,
y.route_id,
min(leg_sequence_id) max_leg_sequence_id
FROM
posimorders.sc_execution_eu.o_detailed_routes_v2 y
LEFT JOIN warehouse_attributes w -- Joining to add origin country of origin FC
ON w.warehouse_id = y.leg_warehouse_id
group by
1,2
) x
INNER JOIN posimorders.sc_execution_eu.o_detailed_routes_v2 y
on x.route_id = y.route_id and x.shipment_id = y.shipment_id and y.leg_sequence_id = x.max_leg_sequence_id
),
list_legs_ds AS(
SELECT t1.*, t2.* FROM
(SELECT leg_warehouse_id, SUM(pck_count) AS total_packages
FROM posimorders.sc_execution_eu.o_detailed_routes_v2
WHERE trunc(cpt_date) between '2019-06-16' and '2019-06-22'
and leg_sequence_id = 0
and leg_warehouse_id not like 'X%'
and right(leg_warehouse_id,1) in ('1','2','3','4','5','6','7','8','9') --Only SC and not Airports
group by 1
having sum(pck_count) > 50000
) t1
CROSS JOIN
(select distinct leg_warehouse_id AS lm_ds , destination_country_code
from posimorders.sc_execution_eu.o_detailed_routes_v2
where trunc(cpt_date) BETWEEN '2019-06-16' and '2019-06-22'
and leg_ship_method LIKE 'AMZN_%_PRIME'
) t2
)
SELECT
a.route_warehouse_id,
--k.leg_warehouse_id leg_ware,
--k.leg_warehouse_id lm_ds,
from
final_leg a
inner join dest_leg b
on a.shipment_id = b.shipment_id and a.route_id = b.route_id
--RIGHT JOIN list_legs_ds k
--on a.leg_warehouse_id = k.leg_ware -- and a.leg_ship_method = k.last_ds

The issue is most likely because you haven't aliased the columns in your list_legs_ds subquery, meaning you have at least two columns with the same name.
This is a good example of why you shouldn't, in general, use select *... and why you should be explicit in the columns you're selecting. Try the following instead:
WITH final_leg AS
(SELECT y.*
FROM (SELECT y.shipment_id,
y.route_id,
MAX(leg_sequence_id) max_leg_sequence_id
FROM posimorders.sc_execution_eu.o_detailed_routes_v2 y
GROUP BY 1,
2) AS x
INNER JOIN posimorders.sc_execution_eu.o_detailed_routes_v2 y
ON x.route_id = y.route_id
AND x.shipment_id = y.shipment_id
AND y.leg_sequence_id = x.max_leg_sequence_id),
dest_leg AS
(SELECT y.*
FROM (SELECT y.shipment_id,
y.route_id,
MIN(leg_sequence_id) max_leg_sequence_id
FROM posimorders.sc_execution_eu.o_detailed_routes_v2 y
LEFT JOIN warehouse_attributes w -- Joining to add origin country of origin FC
ON w.warehouse_id = y.leg_warehouse_id
GROUP BY 1,
2) x
INNER JOIN posimorders.sc_execution_eu.o_detailed_routes_v2 y
ON x.route_id = y.route_id
AND x.shipment_id = y.shipment_id
AND y.leg_sequence_id = x.max_leg_sequence_id),
list_legs_ds AS
(SELECT t1.leg_warehouse_id AS leg_ware,
t1.total_packages,
t2.leg_warehouse_id AS last_ds,
t2.destination_country_code
FROM (SELECT leg_warehouse_id AS leg_ware,
SUM(pck_count) AS total_packages
FROM posimorders.sc_execution_eu.o_detailed_routes_v2
GROUP BY 1
HAVING SUM(pck_count) > 50000) t1
CROSS JOIN (SELECT DISTINCT leg_warehouse_id AS last_ds,
destination_country_code
FROM posimorders.sc_execution_eu.o_detailed_routes_v2) t2)
SELECT a.route_warehouse_id,
k.leg_ware,
k.last_ds lm_ds
-- should there be something to aggregate here?
FROM final_leg a
INNER JOIN dest_leg b
ON a.shipment_id = b.shipment_id
AND a.route_id = b.route_id
RIGHT JOIN list_legs_ds k
ON a.leg_warehouse_id = k.leg_ware -- and a.leg_ship_method = k.lm_ds
GROUP BY 1,
2,
3;

Related

I am trying to combine 3 tables for to get a distinct combination as below

SELECT TYPE_DETAILS(a.column1,c.column2,c.column3) BULK COLLECT INTO OUT_DETAILS
FROM TABLE1 a
INNER JOIN TABLE2 b ON a.column2 = b.column2
INNER JOIN TABLE3 c ON a.column3 = c.column3;
I only want combinations for distinct values of a.column1 . If I apply distinct as below i am getting error
SELECT TYPE_DETAILS(DISTINCT a.column1,c.column2,c.column3) BULK COLLECT INTO OUT_DETAILS
FROM TABLE1 a
INNER JOIN TABLE2 b ON a.column2 = b.column2
INNER JOIN TABLE3 c ON a.column3 = c.column3;
Why don't you use sub-query:
SELECT TYPE_DETAILS(column1,column2,column3)
BULK COLLECT INTO OUT_DETAILS FROM
(SELECT DISTINCT a.column1,c.column2,c.column3
FROM TABLE1 a
INNER JOIN TABLE2 b ON a.column2 = b.column2
INNER JOIN TABLE3 c ON a.column3 = c.column3);

How to add a condition in a WHERE statement based on a JOIN

In my WHERE condition, the following
w.physical_country = y.destination_country_code
works fine except when there is the country United Kingdom. This is because in w.physical_country column the value is 'UK' whereas in y.destination_country_code the value is 'GB'
Hence the where condition will skip this condition as they don't match, whoever in reality they do match and should be added to the table. How would you add a condition to take this into account ?
dest_leg AS(
SELECT y.*
FROM
(
SELECT
y.shipment_id,
y.route_id,
min(leg_sequence_id) max_leg_sequence_id
FROM
posimorders.sc_execution_eu.o_detailed_routes_v2 y
LEFT JOIN warehouse_attributes w -- Joining to add country of dest SC
ON w.warehouse_id = y.leg_warehouse_id
where 1=1
and w.physical_country = y.destination_country_code
group by
1,2
) x
INNER JOIN posimorders.sc_execution_eu.o_detailed_routes_v2 y
on x.route_id = y.route_id and x.shipment_id = y.shipment_id and y.leg_sequence_id = x.max_leg_sequence_id
),
To solve the UK vs GB you can use:
if(w.physical_country='UK','GB',w.physical_country) = y.destination_country_code

How to implement left join on data range in hive

I want to convert the below oracle logic to hive.
Logic:
Select a.id,a.name,b.desc from table a left join table b on
a.num between b.min_num and b.max_num;
Could any one help me out to achieve the above logic in hive.
With this solution you have the control on the performance.
b ranges are being split to sub-ranges, small as you want (x).
Too big x will practically cause a CROSS JOIN.
Too small x might generate a huge set from b (x=1 will generate all b ranges' values).
set hivevar:x=100;
select a.id
,a.name
,b.desc
from table_a as a
left join
(select a.id
,b.desc
from table_a as a
inner join
(select b.min_num div ${hivevar:x} + pe.pos as sub_range_id
,b.*
from table_b as b
lateral view
posexplode(split(space(cast (b.max_num div ${hivevar:x} - b.min_num div ${hivevar:x} as int)),' ')) pe
) as b
on a.num div ${hivevar:x} =
b.sub_range_id
where a.num between b.min_num and b.max_num
) b
on b.id =
a.id
;
select a.id
,a.name
,b.desc
from table_a as a
left join (select a.id
,b.desc
from table_a as a
cross join table_b as b
where a.num between b.min_num and b.max_num
) b
on b.id =
a.id
;
select a.id
,a.name
,b.desc
from table_a as a
left join (select b.min_num + pe.pos as num
,b.desc
from table_b as b
lateral view
posexplode(split(space(b.max_num-b.min_num),' ')) pe
) b
on b.num =
a.num
;

Error when joining CTEs

I have 2 CTE.When i try to join them i get an error message "ORA-01789: ".how can i merge the 2 CTE.Is there any other way to get the desired result?
WITH IMPORT_CTE
AS ((select A.*
FROM IMPORT_REGISTRY_ERROR_LOG_1 A
INNER JOIN (select distinct POD_ID,CONFLICTED_POD_ID,ERROR_CODE
FROM IMPORT_REGISTRY_ERROR_LOG_1
GROUP BY POD_ID,CONFLICTED_POD_ID,ERROR_CODE
HAVING COUNT(*) > 1) B
on A.POD_ID = B.POD_ID AND A.CONFLICTED_POD_ID = B.CONFLICTED_POD_ID AND A.ERROR_CODE = B.ERROR_CODE ) order by a.pod_id desc)
select t1.*
from IMPORT_CTE t1
where t1.insert_date =(select max(t2.insert_date)
from IMPORT_CTE t2
where t2.POD_ID =t1.POD_ID)
WITH IMPORT_CTE1
AS ((select A.*
FROM IMPORT_REGISTRY_ERROR_LOG_1 A
INNER JOIN (select distinct POD_ID,CONFLICTED_POD_ID,ERROR_CODE
FROM IMPORT_REGISTRY_ERROR_LOG_1
GROUP BY POD_ID,CONFLICTED_POD_ID,ERROR_CODE
HAVING COUNT(*) > 1) B
on A.POD_ID = B.POD_ID AND A.CONFLICTED_POD_ID = B.CONFLICTED_POD_ID AND A.ERROR_CODE = B.ERROR_CODE ) order by a.pod_id desc)
select t1.insert_date
from IMPORT_CTE1 t1
where t1.insert_date =(select min(t2.insert_date)
from IMPORT_CTE1 t2
where t2.POD_ID =t1.POD_ID)
You've got an extra set of parentheses in each of your queries. The first one should apparently be:
WITH IMPORT_CTE AS
(select A.*
FROM IMPORT_REGISTRY_ERROR_LOG_1 A
INNER JOIN (select distinct POD_ID,CONFLICTED_POD_ID,ERROR_CODE
FROM IMPORT_REGISTRY_ERROR_LOG_1
GROUP BY POD_ID,CONFLICTED_POD_ID,ERROR_CODE
HAVING COUNT(*) > 1) B
on A.POD_ID = B.POD_ID AND
A.CONFLICTED_POD_ID = B.CONFLICTED_POD_ID AND
A.ERROR_CODE = B.ERROR_CODE
order by a.pod_id desc)
select t1.*
from IMPORT_CTE t1
where t1.insert_date = (select max(t2.insert_date)
from IMPORT_CTE t2
where t2.POD_ID = t1.POD_ID)
The second one has a similar problem.
Best of luck.

Inner join in Linq with more than 2 datatables

i have 3 tables
t1==>
t1.ID t1.co1 t1.col2
1 a b
2 a b
t2==>
t2.ID t2.co1 t2.col2
1 a b
2 a b
t3==>
t3.ID t3.co1 t3.col2
1 a b
2 a b
i want inner join between all three tables using Linq and want selected column in 4th datatable.
equivalent sql query:
SELECT t1.ID,t2.col1,t3.col2
FROM t1
INNER JOIN t2 ON t1.ID=t2.ID
INNER JOIN t3 ON t1.ID=t3.ID
t4==>
t1.ID t2.co1 t3.col2
1 a b
2 a b
Something like this
var Result =
from row1 in t1
join row2 in t2 on row1.ID equals row2.ID
join row3 in t3 on row1.ID equals row3.ID
select new { ID = row1.ID, Col1 = row2.col1, Col2 = row3.col2 }
DataTable dt = Result.CopyToDataTable();
Use LoadDataRow() to get a DataTable from an anonymous type as here. Else Result.CopyToDataTable().
//Get the column list as same as table1 to new datatable
DataTable table4 = table1.Clone();
var Result =
from x in t1.AsEnumerable() join
y in t2.AsEnumerable() on x.Field<int>("ID") equals y.Field<int>("ID") join
z in t3.AsEnumerable() on x.Field<int>("ID") equals z.Field<int>("ID")
select new table4.LoadDataRow(
new object[] {
x.ID,
y.col1,
z.col2
}, false);

Resources