Case when inside cross join lateral? - sql

I have following SQL statement:
WITH report AS (
SELECT reattr.app_id,
reattr.campaign_c AS campaign,
reattr.media_source_pid AS media_source,
reattr.date,
reattr.agency_pmd_af_prt AS agency,
sum(reattr.total_cost) AS total_cost,
sum(reattr.total_revenue) AS total_revenue,
sum(reattr.af_purchase_unique_users) AS af_purchase_unique_users,
sum(reattr.af_purchase_event_counter) AS af_purchase_event_counter,
reattr.conversion_type
FROM a.partners_reattr reattr
GROUP BY reattr.app_id, reattr.campaign_c, reattr.media_source_pid, reattr.date, reattr.agency_pmd_af_prt, reattr.conversion_type
)
SELECT report.app_id,
report.campaign,
report.media_source,
report.agency,
report.date,
case
when report.conversion_type = 're-engagement'::text then 're-engagement'::text
ELSE 'retargeting'::text
END AS metric_type,
v.metric_key,
v.metric_value,
v.metric_name
FROM report
CROSS JOIN LATERAL ( VALUES
('installs'::text, report.conversions,'installs'::text),
('total_cost'::text,report.total_cost,'total_cost'::text),
('event'::text,report.af_purchase_unique_users,'af_purchase_unique_users'::text),
('event'::text,report.af_purchase_event_counter,'af_purchase_event_counter'::text),
('total_revenue'::text,report.total_revenue,'total_revenue'::text))
v(metric_key, metric_value, metric_name)
WHERE v.metric_value IS NOT NULL;
What I want.. If conversion_type = re-engagement then first row in CROSS JOIN LATERAL should be ('conversions'::text, report.conversions,'conversions'::text),.
If conversion_type = re-atribution then it should be ('installs'::text, report.conversions,'installs'::text). So I need smth like CASE - WHEN, but as far as i know, i can't use it inside cross join lateral values? I couldn't apply it. So I need to dynamically set metric_key in first row inside CROSS JOIN LATERAL. Is it possible?

The first entry in your VALUES list could simply be
VALUES (CASE WHEN conversion_type = 're-engagement'
THEN 'conversions'::text
ELSE 'installs'::text
END,
report.conversions,
CASE WHEN conversion_type = 're-engagement'
THEN 'conversions'::text
ELSE 'installs'::text
END), ...

Related

Attempting to use result of Case Expression in a join .. need to improve query

I have the following query which allows me to join the TransactionClass tables base on TransactionClassID from either the primary table (Transactions) or TransactionRules based on a condition as below:
SELECT
Description,
TC.Name,
(CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END) As ClassId
FROM Transactions AS T
LEFT JOIN TransactionRules TR ON T.Description LIKE TR.Pattern
LEFT JOIN TransactionClasses TC ON TC.TransactionClassId =
(CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionClassId
ELSE T.TransactionClassId
END)
The query is running on SQL Server,
In effect, it retrieves the correct TransactionClass entry depending on whether or not the join on TransactionRules was successful or not.
The above query works, but I am trying to simplify the query so that I do not have to repeat the CASE expression in two places.
I attempted to capture the result of the case expression in a variable and use that as follows:
SELECT
Description,
x
FROM Transactions AS T
LEFT JOIN TransactionRules TR
ON T.Description LIKE TR.Pattern
LEFT JOIN TransactionClasses TC
ON TC.TransactionClassId = x
WHERE x = (CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END)
But I get the error:
[S0001][207] Line 8: Invalid column name 'x'.
Where am I going wrong in my attempt to have only one CASE Expression?
CROSS APPLY is a tidy way to reuse a calculated value e.g.
SELECT
[Description]
, TC.[Name]
, Class.Id
FROM Transactions AS T
LEFT JOIN TransactionRules TR ON T.[Description] LIKE TR.Pattern
CROSS APPLY (
VALUES (
CASE
WHEN TR.TransactionRuleId > 0
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END
)
) AS Class (Id)
LEFT JOIN TransactionClasses TC ON TC.TransactionClassId = Class.Id;

Case statement in multiple conditions?

I want to check the column mr.name, if mr.name is null then i have to replace mr.name as mr.ticket_no. How? Can use if else or case?
select ROW_NUMBER() OVER(ORDER BY mr_user) sl_no,* from (select
mr.name as mr_no,
coalesce(mr.user_id,0) as mr_user
from stock_production_lot lot
left join kg_grn grn on (grn.name = lot.grn_no)
left join kg_department_indent mr on (mr.name = grn.mr_no)
order by mr.user_id) main
where mr_user=65
When i use like this
case when mr.name is null then '' else mr.ticket_no = grn.mr_no as mr_no
it will throw an error
if mr.name = null means i have to replace mr.name = mr.ticket_no. I want to check the column mr.name, if mr.name is null then i have to replace mr.name as mr.ticket_no
You can use coalesce() to replace null with anything:
select ROW_NUMBER() OVER(ORDER BY mr_user) sl_no,* from (select
coalesce(mr.name,mr.ticket_no) as mr_no,
coalesce(mr.user_id,0) as mr_user
from stock_production_lot lot
left join kg_grn grn on (grn.name = lot.grn_no)
left join kg_department_indent mr on (mr.name = grn.mr_no)
order by mr.user_id) main
where mr_user=65
But if you are comfortable with case when then use as below:
select ROW_NUMBER() OVER(ORDER BY mr_user) sl_no,* from (select
(case when mr.name is null then mr.ticket_no else mr.name end) as mr_no,
coalesce(mr.user_id,0) as mr_user
from stock_production_lot lot
left join kg_grn grn on (grn.name = lot.grn_no)
left join kg_department_indent mr on (mr.name = grn.mr_no)
order by mr.user_id) main
where mr_user=65

SQL Error when using LIKE CASE WHEN with subquery

I'm attempting to write an SQL statement that use Excel parameters to insert data via a drop down menu. This normally works great, but I think because I'm using a subquery in this case I'm getting the error "The multi-part identifier could not be bound." The subquery is used to create a sum of the quantity of an item purchased within the past week. Here's the code:
SELECT DISTINCT ITMMASTER.ITMREF_0 AS ITEMCODE, ITMMASTER.ITMDES1_0 AS ITEMDESC, Sum(ITMMVT.PHYSTO_0) AS AVAILSTOCK, Sum(ITMMVT.ORDSTO_0) AS ONORDER, Sum(ITMMVT.PHYALL_0) AS ALLOCATED, Sum(ITMFACILIT.MAXSTO_0) AS MAX,
INVQTY = (SELECT Sum(SINVOICED.QTY_0) AS INVQTY
FROM x3v11.PROD.SINVOICED SINVOICED
WHERE SINVOICED.INVDAT_0 BETWEEN DATEADD(WEEK,-1,DATEADD(WEEK,DATEDIFF(WEEK,0,GETDATE()),0))
AND DATEADD(DAY,4,DATEADD(WEEK,-1,DATEADD(WEEK,DATEDIFF(WEEK,0,GETDATE()),0)))
AND SINVOICED.ITMREF_0 = ITMMASTER.ITMREF_0
),
ITMMASTER.ITMWEI_0 AS WEIGHT, ITMCOST.CSTTOT_0 AS COST, ITMBPS.BPSNUM_0 AS VENDOR, BPSUPPLIER.BPSNAM_0 AS VENDNAME, ITMMASTER.TSICOD_2 AS CAT
FROM x3v11.PROD.ITMMASTER ITMMASTER
LEFT OUTER JOIN x3v11.PROD.ITMMVT ITMMVT ON ITMMASTER.ITMREF_0 = ITMMVT.ITMREF_0
LEFT OUTER JOIN x3v11.PROD.ITMFACILIT ITMFACILIT ON ITMMVT.ITMREF_0 = ITMFACILIT.ITMREF_0 AND ITMMVT.STOFCY_0 = ITMFACILIT.STOFCY_0
LEFT OUTER JOIN x3v11.PROD.ITMCOST ITMCOST ON ITMMVT.ITMREF_0 = ITMCOST.ITMREF_0 AND ITMMVT.STOFCY_0 = ITMCOST.STOFCY_0
LEFT OUTER JOIN x3v11.PROD.ITMBPS ITMBPS ON ITMMASTER.ITMREF_0 = ITMBPS.ITMREF_0
LEFT OUTER JOIN x3v11.PROD.BPSUPPLIER BPSUPPLIER ON ITMBPS.BPSNUM_0 = BPSUPPLIER.BPSNUM_0
WHERE ITMCOST.STOFCY_0 <> '115'
AND ITMFACILIT.MAXSTO_0 <> 0
AND ITMBPS.PIO_0 <> 99
AND ITMBPS.BPSNUM_0 LIKE CASE WHEN ? IS NOT NULL THEN ? ELSE '%' END
GROUP BY ITMMASTER.ITMREF_0, ITMMASTER.ITMDES1_0, ITMMASTER.ITMWEI_0, ITMCOST.CSTTOT_0, ITMBPS.BPSNUM_0, BPSUPPLIER.BPSNAM_0, ITMMASTER.TSICOD_2
ORDER BY ITMMASTER.ITMREF_0
I think you have specified the syntax for the subquery incorrectly:
INVQTY = (SELECT Sum(SINVOICED.QTY_0) AS INVQTY
FROM x3v11.PROD.SINVOICED SINVOICED
WHERE SINVOICED.INVDAT_0 BETWEEN
DATEADD(WEEK,-1,DATEADD(WEEK,DATEDIFF(WEEK,0,GETDATE()),0))
AND DATEADD(DAY,4,DATEADD(WEEK,-1,DATEADD(WEEK,DATEDIFF(WEEK,0,GETDATE()),0)))
AND SINVOICED.ITMREF_0 = ITMMASTER.ITMREF_0
),
I think it should be:
(SELECT Sum(SINVOICED.QTY_0)
FROM x3v11.PROD.SINVOICED SINVOICED
WHERE SINVOICED.INVDAT_0 BETWEEN
DATEADD(WEEK,-1,DATEADD(WEEK,DATEDIFF(WEEK,0,GETDATE()),0))
AND DATEADD(DAY,4,DATEADD(WEEK,-1,DATEADD(WEEK,DATEDIFF(WEEK,0,GETDATE()),0)))
AND SINVOICED.ITMREF_0 = ITMMASTER.ITMREF_0
) AS INVQTY,

Tereadata Error 3782 Improper column reference in the search condition of a joined table

I made some changes (highlighted below) to some sql I inherited and I'm getting
Error 3782 Improper column reference in the search condition of a
joined table
I'm not sure why I'm getting this message. Any help would be greatly appreciated.
with dqry_cc (mop_cd, mop_desc, group_branch_id, ecr_tmz_name, stn_stn_id , stn_id, grp_brn_id ) as
(select
a.mop_cd ,
a.mop_desc,
so.group_branch_id ,
t.ecr_tmz_name,
so.stn_stn_id,
s.stn_id ,
s.grp_brn_id
from
rfs.stn_ops_hierarchies so,
rfs.mthd_of_pymts a,
rfs.stns s,
rfs.tmzs_map t
where s.stn_id = so.stn_stn_id
and a.mpt_mop_type_code = 'CC'
and s.TMZ = t.TMZS_TMZ
and so.group_id = '01'
and so.region_cd = 'RGN_stl_99'
and so.group_branch_id ='0101')
select *
from
(select
cc.group_branch_id as GpBr,
cc.mop_desc as Descr,
cast(SYSLIB.ERAC_GMT_TO_LCL(ph.pymt_dt, cc.ecr_tmz_name) AS timestamp(6)) as LocalPaydate,
cast(SYSLIB.ERAC_GMT_TO_LCL(ph.pymt_dt, cc.ecr_tmz_name) as date) as ph_pymt_dt,
dr.dvr_srnm as DriverFName,
dr.dvr_frst_name as DriverLName,
ph.name as HolderName,
pd.ticket_no as ECARS2,
cast( case when rb.ecr_lgcy_resv_nbr is null then
case when substr(pd.ticket_no,1,1) = 'D' then
'D'||substr(pd.ticket_no, 2,6)
else
null
end
else 'D'||rb.ecr_lgcy_resv_nbr
end as CHAR(7)) as ECARS1,
rb.rnt_agr_nbr as RntAgrNo,
case when ph.cr_card_trans_typ_cde='R' then
-1*pd.pymt_amt
else
pd.pymt_amt
end as AMOUNT,
pd.cur_curr_cd as Curr,
ph.CR_CARD_NBR as CardNo,
cast(ph.exp_dt as date format 'mm/yy') as ExpireDate,
cast(0 as decimal(15,3)) as AUTH_AMT,
cast(null as date format 'mm/dd/yyyy') as AuthDate,
ph.auth_nbr as AuthNo,
cast(null as char(2)) as Swipe,
cast(null as varchar(60)) as PType,
**pft.Settlement,
pft.First_Six**
from
dqry_cc cc,
rfs_rv.pre_applied_pymts_hdr ph,
rfs_rv.pre_applied_pymts_det pd
left outer join
(select
ra.rnt_agr_nbr,
ra.ecr_ticket_no,
ra.ecre_rent_cntrct_nbr,
ra.ecr_lgcy_resv_nbr,
cc.grp_brn_id --
from
rfs_rv.rnt_agrs ra,
dqry_cc cc
where ra.sta_stn_id_orig_co = cc.stn_id QUALIFY ROW_NUMBER() OVER(PARTITION BY ra.rnt_agr_nbr ORDER BY ra.rnt_agr_nbr) = 1
) rb
on pd.ticket_no = rb.ecr_ticket_no
left outer join
(select
dvr.dvr_srnm,
dvr.dvr_frst_name,
dvr.rdy_rnt_agr_nbr
from rfs_rv.dvr_rras dvr
where dvr.main_dvr_flg = 'MR'
) dr
on rb.rnt_agr_nbr = dr.rdy_rnt_agr_nbr
**left outer join
(select
ft.paymt_mdia_proc_sys_cde as Settlement,
ft.prim_acct_frst_six_dgt_nbr as First_Six,
ft.fin_tran_ref_id
from paymt.fin_tran ft) pft
on pft.fin_tran_ref_id = cast(ph.paph_fin_trans_ref_id as decimal(19,0))**
where ph.pymt_stn_id = cc.stn_stn_id
and ph.mop_mop_cd = cc.mop_cd
and ph.pymt_id = pd.pap_pymt_id
and ph_pymt_dt = 8/5/2015
) z
Your a mixing old and new style join syntax. Your problem would never exist if you followed this simple rule: Never use commas the FROM clause. Always use explicit JOIN syntax.
The problem is the scoping of around the comma operator. Although it is functionally equivalent to a CROSS JOIN, the first part is not a known alias for the second part.
If you fix FROM to remove all commas, your problem will be fixed, even if you only change the comma to a CROSS JOIN. However, I recommend using the proper JOIN.

How to replace a NULL when a COUNT(*) returns NULL in DB2

I have a query:
SELECT A.AHSHMT AS SHIPMENT, A.AHVNAM AS VENDOR_NAME, D.UNITS_SHIPPED, D.ADPON AS PO, B.NUMBER_OF_CASES_ON_TRANSIT, C.NUMBER_OF_CASES_RECEIVED FROM AHASNF00 A
INNER JOIN (SELECT IDSHMT, COUNT(*) AS NUMBER_OF_CASES_ON_TRANSIT FROM IDCASE00 WHERE IDSTAT = '01' GROUP BY IDSHMT) B
ON (A.AHSHMT = B.IDSHMT)
LEFT JOIN (SELECT IDSHMT, (COUNT(*) AS NUMBER_OF_CASES_RECEIVED FROM IDCASE00 WHERE IDSTAT = '10' GROUP BY IDSHMT) C
ON (A.AHSHMT = C.IDSHMT)
INNER JOIN (SELECT ADSHMT, ADPON, SUM(ADUNSH) AS UNITS_SHIPPED FROM ADASNF00 GROUP BY ADSHMT, ADPON) D
ON (A.AHSHMT = D.ADSHMT)
WHERE A.AHSHMT = '540041134';
On the first JOIN statement I have a COUNT(*), on this count sometimes I will get NULL. I need to replace this with a "0-zero", I know think I know how to do it in SQL
ISNULL(COUNT(*), 0)
But this doesn't work for DB2, how can I accomplish this? All your help is really appreciate it.
Wrap a COALESCE around each of the nullable totals in your SELECT list:
SELECT A.AHSHMT AS SHIPMENT,
A.AHVNAM AS VENDOR_NAME,
COALESCE( D.UNITS_SHIPPED, 0 ) AS UNITS_SHIPPED,
D.ADPON AS PO,
COALESCE( B.NUMBER_OF_CASES_ON_TRANSIT, 0 ) AS NUMBER_OF_CASES_ON_TRANSIT,
COALESCE( C.NUMBER_OF_CASES_RECEIVED, 0 ) AS NUMBER_OF_CASES_RECEIVED
FROM ...
The inner joins you're using for expressions B and D mean that you will only receive rows from A that have one or more cases in transit (expression B) and have one or more POs in expression D. Is that the way you want your query to work?
Instead of using ISNULL(COUNT(*), 0),
try using COALESCE(COUNT(*),0)
use IFNULL(COUNT(*), 0) for DB2