DB2 Alternate to EXISTS Function - sql

I have the below query in my application which was running on DB2:
SELECT COD.POST_CD,CLS.CLASS,COD2.STATUS_CD
FROM DC01.POSTAL_CODES COD
INNER JOIN DC02.STATUS_CODES COD2
ON COD.ORDER=COD2.ORDER
INNER JOIN DC02.VALID_ORDERS ORD
ON ORD.ORDER=COD.ORDER
WHERE
(
( EXISTS (SELECT 1 FROM DC00.PROCESS_ORDER PRD
WHERE PRD.ORDER=COD.ORDER
AND PRD.IDNUM=COD.IDNUM
)
) OR
( EXISTS (SELECT 1 FROM DC00.PENDING_ORDER PND
WHERE PND.ORDER=COD.ORDER
AND PND.IDNUM=COD.IDNUM
)
)
)
AND EXISTS (SELECT 1 FROM DC00.CUSTOM_ORDER CRD
WHERE CRD.ORDER=COD.ORDER
)
;
When we changed to UDB (LUW v9.5) we are getting the below warning:
IWAQ0003W SQL warnings were found
SQLState=01602 Performance of this complex query might be sub-optimal.
Reason code: "3".. SQLCODE=437, SQLSTATE=01602, DRIVER=4.13.111
I know this warning is due to the EXISTS () OR EXISTS statements. But I am not sure any other way I can write this query to replace. If it is AND, I could have made an INNER JOIN, but I am not able to change this condition as it is OR. Can any one suggest better way to replace these EXISTS Statements?

SELECT COD.POST_CD,CLS.CLASS,COD2.STATUS_CD
FROM DC01.POSTAL_CODES COD
INNER JOIN DC02.STATUS_CODES COD2
ON COD.ORDER=COD2.ORDER
INNER JOIN DC02.VALID_ORDERS ORD
ON ORD.ORDER=COD.ORDER
WHERE
(
EXISTS SELECT 1 FROM
(SELECT ORDER,IDNUM FROM DC00.PROCESS_ORDER PRD UNION
SELECT ORDER,IDNUM FROM DC00.PENDING_ORDER PND) PD
WHERE PD.ORDER=COD.ORDER
AND PD.IDNUM=COD.IDNUM
)
AND EXISTS (SELECT 1 FROM DC00.CUSTOM_ORDER CRD
WHERE CRD.ORDER=COD.ORDER
)
;

Related

Oracle SQL Developer - error when referencing fields within nested from statements

For the below query I am getting an error with line 4 when referencing variables within "y". The query runs successfully when I use just " y.* " (line 5), however it generates an error when I try to also pull from the specified fields in line 4 (y.field1 as PRODUCT, y.field2 as PRODUCT_TYPE, y.entity, y.TYPE1). For the output, I want these fields listed first for visual reference.
I have this approach/ logic working for other queries (as i'm re using this logic for multiple variations of queries and various tables). However, I think that the issue with this one lies in my attempt to reference fields from tables that are in my join statements.
(
select
-- categorization fields:
-- table2.field1 as PRODUCT, table2.field2 as PRODUCT_TYPE, table3.entity, table3.TYPE1
y.field1 as PRODUCT,
y.field2 as PRODUCT_TYPE,
y.entity,
y.TYPE1
,y.*
from (
select *
from (
-- table references:
select table1.*,
row_number() over (
partition by
-- categorization fields:
table2.field1,
table2.field2,
table3.entity,
table3.TYPE1
order by table3.entity
) as rn
-- table references
from table1
-- joins, links, and filtering:
inner join table6 on table1.field_1 = table6.code1
inner join table5 on (table6.code = table5.code1)
AND (table6.code = table5.code)
left join table3 on table6.ent1 = table3.ent_code
left join table2 on table1.extid = table2.extID
where table1.tdate between '01-APR-19' and '01-APR-21'
AND table1.refe NOT IN ('OFF')
) x
-- sample rows:
where rn <= 2
) y
);
Let me know if anyone has a way that I can maybe better specify which tables those fields come from. I wish I could just do something like this:
y.table2.field1 as PRODUCT,
y.table2.field2 as PRODUCT_TYPE,
y.table3.entity,
y.table3.TYPE1
Sorry that I don't have a fiddle available!
Let me know if anyone has a way that I can maybe better specify which tables those fields come from.
Don't use select *. Instead, use the column names and give them appropriate aliases so you know where they came from:
As an example:
SELECT small_value,
medium_value,
big_value
FROM (
SELECT small.value AS small_value,
medium.value AS medium_value,
big.value AS big_value
FROM big
CROSS JOIN medium
CROSS JOIN small
)
WHERE 1 = 1
In your query, instead of using SELECT * in y or using SELECT table1.* in x you can name the columns and give them descriptive aliases.
I am getting an error with line 4 when referencing variables within "y".
(
select
-- categorization fields:
-- table2.field1 as PRODUCT, table2.field2 as PRODUCT_TYPE, table3.entity, table3.TYPE1
That is because you cannot see TABLE2 or TABLE3 because the only "view" you are looking at is of the sub-query with the alias y.
If you want to see those columns then you need to SELECT them inside the x subquery and pass them to each subsequent outer-query.
(
select *
from (
-- table references:
select table1.field1 AS t1_product,
table1.field2 AS t1_product_type,
table1.entity AS t1_entity,
table1.type1 AS t1_type1,
table2.field1 AS t2_product,
table2.field2 AS t2_product_type,
table2.entity AS t2_entity,
table2.type1 AS t2_type1,
table3.field1 AS t3_product,
table3.field2 AS t3_product_type,
table3.entity AS t3_entity,
table3.type1 AS t3_type1,
row_number() over (
partition by
-- categorization fields:
table2.field1,
table2.field2,
table3.entity,
table3.TYPE1
order by table3.entity
) as rn
-- table references
from table1
-- joins, links, and filtering:
inner join table6 on table1.field_1 = table6.code1
inner join table5 on (table6.code = table5.code1)
AND (table6.code = table5.code)
left join table3 on table6.ent1 = table3.ent_code
left join table2 on table1.extid = table2.extID
where table1.tdate between '01-APR-19' and '01-APR-21'
AND table1.refe NOT IN ('OFF')
) x
-- sample rows:
where rn <= 2
);

ERROR SQL Server ONLY one expression can be specified in the select list when the subquery is not introduced with exists

I am trying to run my query but I get an error.
This is my query:
if exists (select CODE_ISIN
from cte
where code_ISIN not in (select [STATUT_TITRE], [CODE_ISIN]
from TT_TITRE A
inner join TT_STATUT_TITRE B on A.TITRE_ID = B.TITRE_ID))
begin
select 'ko'
end
begin
select 'ok'
end
Remove [STATUT_TITRE] from sub-query as it will accept only one expression :
select c.CODE_ISIN
from cte c
where code_ISIN not in (select [CODE_ISIN] -- only one expression needed
from TT_TITRE A inner join
TT_STATUT_TITRE B
on A.TITRE_ID = B.TITRE_ID
);
I would suggest to use NOT EXISTS instead :
where not exists (select 1
from TT_TITRE A inner join
TT_STATUT_TITRE B
on A.TITRE_ID=B.TITRE_ID
where CODE_ISIN = c.CODE_ISIN
);

Unable to convert this legacy SQL into Standard SQL in Google BigQuery

I am not able to validate this legacy sql into standard bigquery sql as I don't know what else is required to change here(This query fails during validation if I choose standard SQL as big query dialect):
SELECT
lineitem.*,
proposal_lineitem.*,
porder.*,
company.*,
product.*,
proposal.*,
trafficker.name,
salesperson.name,
rate_card.*
FROM (
SELECT
*
FROM
dfp_data.dfp_order_lineitem
WHERE
DATE(end_datetime) >= DATE(DATE_ADD(CURRENT_TIMESTAMP(), -1, 'YEAR'))
OR end_datetime IS NULL ) lineitem
JOIN (
SELECT
*
FROM
dfp_data.dfp_order) porder
ON
lineitem.order_id = porder.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_proposal_lineitem) proposal_lineitem
ON
lineitem.id = proposal_lineitem.dfp_lineitem_id
JOIN (
SELECT
*
FROM
dfp_data.dfp_company) company
ON
porder.advertiser_id = company.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_product) product
ON
proposal_lineitem.product_id=product.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_proposal) proposal
ON
proposal_lineitem.proposal_id=proposal.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_rate_card) rate_card
ON
proposal_lineitem.ratecard_id=rate_card.id
LEFT JOIN (
SELECT
id,
name
FROM
dfp_data.dfp_user) trafficker
ON
porder.trafficker_id =trafficker.id
LEFT JOIN (
SELECT
id,
name
FROM
dfp_data.dfp_user) salesperson
ON
porder. salesperson_id =salesperson.id
Most likely the error you are getting is something like below
Duplicate column names in the result are not supported. Found duplicate(s): name
Legacy SQL adjust trafficker.name and salesperson.name in your SELECT statement into respectively trafficker_name and salesperson_name thus effectively eliminating column names duplication
Standard SQL behaves differently and treat both those columns as named name thus producing duplication case. To avoid it - you just need to provide aliases as in example below
SELECT
lineitem.*,
proposal_lineitem.*,
porder.*,
company.*,
product.*,
proposal.*,
trafficker.name AS trafficker_name,
salesperson.name AS salesperson_name,
rate_card.*
FROM ( ...
You can easily check above explained using below simplified/dummy queries
#legacySQL
SELECT
porder.*,
trafficker.name,
salesperson.name
FROM (
SELECT 1 order_id, 'abc' order_name, 1 trafficker_id, 2 salesperson_id
) porder
LEFT JOIN (SELECT 1 id, 'trafficker' name) trafficker
ON porder.trafficker_id =trafficker.id
LEFT JOIN (SELECT 2 id, 'salesperson' name ) salesperson
ON porder. salesperson_id =salesperson.id
and
#standardSQL
SELECT
porder.*,
trafficker.name AS trafficker_name,
salesperson.name AS salesperson_name
FROM (
SELECT 1 order_id, 'abc' order_name, 1 trafficker_id, 2 salesperson_id
) porder
LEFT JOIN (SELECT 1 id, 'trafficker' name) trafficker
ON porder.trafficker_id =trafficker.id
LEFT JOIN (SELECT 2 id, 'salesperson' name ) salesperson
ON porder. salesperson_id =salesperson.id
Note: if you have more duplicate names - you need to alias all of them too

Oracle SQL XOR condition with > 14 tables

I have a question on sql desgin.
Context:
I have a table called t_master and 13 other tables (lets call them a,b,c... for simplicity) where it needs to compared.
Logic:
t_master will be compared to table 'a' where t_master.gen_val =
a.value.
If record exist in t_master, retrieve t_master record, else retrieve 'a' record.
I do not need to retrieve the records if it exists in both tables (t_master and a) - XOR condition
Repeat this comparison with the remaining 12 tables.
I have some idea on doing this, using WITH to subquery the non-master tables (a,b,c...) first with their respective WHERE clause.
Then use XOR statement to retrieve the records.
Something like
WITH a AS (SELECT ...),
b AS (SELECT ...)
SELECT field1,field2...
FROM t_master FULL OUTER JOIN a FULL OUTER JOIN b FULL OUTER JOIN c...
ON t_master.gen_value = a.value
WHERE ((field1 = x OR field2 = y ) AND NOT (field1 = x AND field2 = y))
AND ....
.
.
.
.
Seeing that I have 13 tables that I need to full outer join, is there a better way/design to handle this?
Otherwise I would have at least 2*13 lines of WHERE clause which I'm not sure if that will have impact on the performance as t_master is sort of a log table.
**Assume I cant change any schema.
Currently I'm not sure if this SQL will working correctly yet, so I'm hoping someone can guide me in the right direction regarding this.
update from used_by_already's suggestion:
This is what I'm trying to do (comparison between 2 tables first, before I add more, but I am unable to get values from ATP_R.TBL_HI_HDR HI_HDR as it is in the NOT EXISTS subquery.
How do i overcome this?
SELECT LOG_REPO.UNIQ_ID,
LOG_REPO.REQUEST_PAYLOAD,
LOG_REPO.GEN_VAL,
LOG_REPO.CREATED_BY,
TO_CHAR(LOG_REPO.CREATED_DT,'DD/MM/YYYY') AS CREATED_DT,
HI_HDR.HI_NO R_VALUE,
HI_HDR.CREATED_BY R_CREATED_BY,
TO_CHAR(HI_HDR.CREATED_DT,'DD/MM/YYYY') AS R_CREATED_DT
FROM ATP_COMMON.VW_CMN_LOG_GEN_REPO LOG_REPO JOIN ATP_R.TBL_HI_HDR HI_HDR ON LOG_REPO.GEN_VAL = HI_HDR.HI_NO
WHERE NOT EXISTS
(SELECT NULL
FROM ATP_R.TBL_HI_HDR HI_HDR
WHERE LOG_REPO.GEN_VAL = HI_HDR.HI_NO
)
UNION ALL
SELECT LOG_REPO.UNIQ_ID,
LOG_REPO.REQUEST_PAYLOAD,
LOG_REPO.GEN_VAL,
LOG_REPO.CREATED_BY,
TO_CHAR(LOG_REPO.CREATED_DT,'DD/MM/YYYY') AS CREATED_DT,
HI_HDR.HI_NO R_VALUE,
HI_HDR.CREATED_BY R_CREATED_BY,
TO_CHAR(HI_HDR.CREATED_DT,'DD/MM/YYYY') AS R_CREATED_DT
FROM ATP_R.TBL_HI_HDR HI_HDR JOIN ATP_COMMON.VW_CMN_LOG_GEN_REPO LOG_REPO ON HI_HDR.HI_NO = LOG_REPO.GEN_VAL
WHERE NOT EXISTS
(SELECT NULL
FROM ATP_COMMON.VW_CMN_LOG_GEN_REPO LOG_REPO
WHERE HI_HDR.HI_NO = LOG_REPO.GEN_VAL
)
Full outer joins used to exclude all matching rows can be an expensive query. You don't supply much detail, but perhaps using NOT EXISTS would be simpler and maybe it will produce a better explain plan. Something along these lines.
select
cola,colb,colc
from t_master m
where not exists (
select null from a where m.keycol = a.fk_to_m
)
and not exists (
select null from b where m.keycol = b.fk_to_m
)
and not exists (
select null from c where m.keycol = c.fk_to_m
)
union all
select
cola,colb,colc from a
where not exists (
select null from t_master m where a.fk_to_m = m.keycol
)
union all
select
cola,colb,colc from b
where not exists (
select null from t_master m where b.fk_to_m = m.keycol
)
union all
select
cola,colb,colc from c
where not exists (
select null from t_master m where c.fk_to_m = m.keycol
)
You could union the 13 a,b,c ... tables to simplify the coding, but that may not perform so well.

How do I join these two selects, what am I doing wrong?

Ok the task at hand is
Obtain the sum of the prizes that have been distributed the exhibitions, until August 31, 2017, for collections and photos. We assume that the awards have never been deserted.
And my code is more or less this
select t1.exhibitions, t2.exhibitions
from (
select exhibitions.premioc
from exhibitions
where EXISTS (select exhibitions.priceC
from exhibitions
join presentCo on exhibitions.id_e = presentCo.id_e
where presentaco.premiada > 0
group by exhibitions.priceC
)
) as t1
left outer join (select exhibitions
from exhibitions
where EXISTS (select exhibitions.priceF
from exhibitions
join presentFo on exhibitions.id_e = presentFo.id_e
where presentafo.preiceC > 0
group by exhibitions.priceF
)
) as "t2"
on t1.exhibitions= t2.exhibitions;
My problem is that I kinda don't know enough of the syntax in SQL and fumbling last minute before delivery (school assignment). I have tried to search and get things to work but I have no idea what I am doing wrong with this part. Any pointer would be awesome. Thank you very much for anything
Edit: being way to late in the night when I posted it I never mentioned the real problem, I get SQL Error: ORA-00933: SQL command not properly ended and don't really get why.
for:
sum of all prizes
distributed at exhibitions, until August 31, 2017
a query would look something like this:
select sum(prize_money)
from exhibitions
where exhibition_date < '2017-09-01'
I suspect the answer is much simpler then you first thought
----
Your existing query has several problems that I an see:
select t1.exhibitions -- this column is not returned by subquery t1
, t2.exhibitions
from (
select exhibitions.premioc -- only this column is returned by subquery t1
from exhibitions
where EXISTS -- when using EXISTS you need a "correlation" inside the where clause of the subquery
(select exhibitions.priceC
from exhibitions
join presentCo on exhibitions.id_e = presentCo.id_e
where presentaco.premiada > 0 -- there is NO "correlation" here
group by exhibitions.priceC
)
) as t1
left outer join (select exhibitions
from exhibitions
where EXISTS ( -- when using EXISTS you need a "correlation" inside the where clause of the subquery
select exhibitions.priceF
from exhibitions
join presentFo on exhibitions.id_e = presentFo.id_e
where presentafo.preiceC > 0 -- there is NO "correlation" here
group by exhibitions.priceF
)
) as "t2"
on t1.exhibitions= t2.exhibitions;
----
I suggest you need to start new, maybe with this as a starting point?
SELECT
exhibitions.id_e
, COALESCE(c.prize_c, 0) prize_c
, COALESCE(f.prize_f, 0) prize_f
FROM exhibitions
LEFT JOIN (
SELECT
presentCo.id_e
, SUM(prize) prize_c
FROM presentCo
GROUP BY
presentCo.id_e
) AS c ON exhibitions.id_e = c.id_e
LEFT JOIN (
SELECT
presentFo.id_e
, SUM(proze) price_f
FROM presentFo
GROUP BY
presentFo.id_e
) AS f ON exhibitions.id_e = presentFo.id_e
But I shall not attempt further suggestions unless I see "sample data" (for each table) and, the "expected result"