case or if else in a where clause Sql Server - sql-server-2012

I using the following query and I am using case statement in where cause with parmeters
when report_type = 'All' then I need all rows and no selection is necessary, however if I select 'AR' or 'BD' I only need those respective statements to be included. However when I tried implement the following logic it is throwing me and error near by OR not sure where I am doing wrong. Any help will be greatly appreciated.
select * from aging agedet where
(
'All' = {?Report_Type}
OR
(
CASE
WHEN {?Report_type} = 'AR' THEN
(agedet.bkt_type_ha_c <> 5
AND
agedet.extern_ar_flag_yn <> 'Y'
AND
agedet.bad_debt_flag_yn <> 'Y')
CASE
WHEN {?Report_type} = 'Bd' THEN
(agedet.bkt_type_ha_c = 5
AND
agedet.extern_ar_flag_yn = 'Y'
AND
agedet.bad_debt_flag_yn = 'Y')
END )
)

Related

Issue with CASE statement nested in WHERE statement containing PROMPT and IN

I am using SQL inside Oracle Cloud BI Publisher product, so I assume this is true SQL or PL/SQL. I am trying to satisfy the following condition: When a user selects accounting period 12 (December) I need the query to fetch all data for periods 12 and 13 (December and Adjustment, respectively). When I get a parenthesis, single quote combo, or nested Select statement which works; the selecting of the prompt (:p_month) of 12 results in an "invalid number" return. Changing the parenthesis, quote stuff other ways yields a direct error from the query when trying to save.
I have tried the following with the grouped result for the portion after THEN:
"invalid number" returns from prompt evaluation of statement passed:
('12''13')
('12,13')
(SELECT '12,13' from dual)
(SELECT "'12','13'" from dual)
"invalid identifier" from query direct:
(SELECT "12,13" from dual)
(SELECT "'12,13'" from dual)
"missing right parenthesis" from query direct:
(''12','13'')
('12','13')
The offending code line is directly below with the full code below that:
AND gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN ('12','13') ELSE (:p_month) END)
SELECT
LPAD(gl_periods.period_num, 2,'0') AS period_num
,gl_periods.period_year AS period_year
,gl_code_combinations.segment1 AS segment1
,gl_code_combinations.segment2 AS segment2
,gl_code_combinations.segment3 AS segment3
,gl_code_combinations.segment4 AS segment4
,gl_code_combinations.segment5 AS segment5
,gl_code_combinations.segment6 AS segment6
,gl_code_combinations.segment7 AS segment7
,gl_ledgers.name AS ledger_name
,gl_ledgers.currency_code AS currency_code
,gl_balances.begin_balance_dr_beq AS begin_balance_dr
,gl_balances.begin_balance_cr_beq AS begin_balance_cr
,gl_balances.period_net_dr_beq AS activity_dr
,gl_balances.period_net_cr_beq AS activity_cr
,(SELECT DISTINCT
fnd_flex_values_vl.attribute1
FROM
fnd_flex_values_vl,
fnd_flex_value_sets
WHERE
1=1
AND fnd_flex_values_vl.flex_value = gl_code_combinations.segment2
AND fnd_flex_values_vl.flex_value_set_id = fnd_flex_value_sets.flex_value_set_id
AND fnd_flex_value_sets.flex_value_set_name = 'CostCenter XXX Enterprise') AS reporting_unit_code
,(SELECT DISTINCT
fnd_flex_values_vl.attribute7
FROM
fnd_flex_values_vl,
fnd_flex_value_sets
WHERE
1=1
AND fnd_flex_values_vl.flex_value = gl_code_combinations.segment2
AND fnd_flex_values_vl.flex_value_set_id = fnd_flex_value_sets.flex_value_set_id
AND fnd_flex_value_sets.flex_value_set_name = 'CostCenter XXX Enterprise') AS operating_country_code
,(SELECT DISTINCT
fnd_flex_values_vl.attribute6
FROM
fnd_flex_values_vl,
fnd_flex_value_sets
WHERE
1=1
AND fnd_flex_values_vl.flex_value = gl_code_combinations.segment2
AND fnd_flex_values_vl.flex_value_set_id = fnd_flex_value_sets.flex_value_set_id
AND fnd_flex_value_sets.flex_value_set_name = 'CostCenter XXX Enterprise') AS legal_country_code
FROM
gl_balances
INNER JOIN gl_code_combinations ON gl_balances.code_combination_id = gl_code_combinations.code_combination_id
INNER JOIN gl_ledgers ON gl_ledgers.ledger_id = gl_balances.ledger_id
INNER JOIN gl_periods ON gl_balances.period_name = gl_periods.period_name
WHERE
1=1
AND gl_balances.currency_code <> 'STAT'
AND gl_balances.actual_flag = 'A'
AND gl_periods.period_set_name = 'XXX Enterprise'
AND gl_code_combinations.account_type IN ('A','L','O')
AND (gl_balances.translated_flag IN ('N','R') OR gl_balances.translated_flag IS NULL)
AND (gl_ledgers.ledger_id IN (:p_ledger) OR LEAST (:p_ledger) IS NULL)
AND gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN ('12','13') ELSE (:p_month) END)
AND (gl_periods.period_year IN (:p_year) OR LEAST (:p_year) IS NULL)
AND gl_ledgers.ledger_category_code = 'PRIMARY'
AND gl_ledgers.name NOT LIKE ('%SL%')
I was able to get the return I wanted with the following code snippet:
AND (
(gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN '12' ELSE (:p_month) END))
OR
(gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN '13' ELSE (:p_month) END))
)
If there is a more elegant answer, I would love to see it as I am always open to new ideas.

postgrelsql error message : syntax error at or near "ELSE"

I'm getting an error with the following SQL query
SELECT b.mo_id,
b.ot_id, (select ot_name from object_type where ot_id = b.ot_id
)ot_name,
a.obj_id, b.pt_id, b.pt_name, b.data_type, a.prop_value1,
CASE
WHEN b.data_type = '2'
THEN (SELECT code_name FROM site_code WHERE group_seq = b.group_seq AND code_seq = a.prop_value1)
WHEN b.data_type = '3' THEN TO_CHAR(a.prop_value1,'999,999,999,999,999')
WHEN b.data_type = '5' AND a.prop_value1 is not null THEN TO_CHAR(to_date(a.prop_value1,'YYYYMMDD'),'YYYY/MM/DD')
WHEN b.data_type = '6' THEN TO_CHAR(a.prop_value1,'999,999,999,999,999')
WHEN b.pt_id = '12003' THEN CONCAT_WS('', SUBSTR(a.prop_value1,0,18) ,
case when length(a.prop_value1) > 18 then '...' else '' end ELSE a.prop_value1
END prop_value1_view, b.pt_order, b.default_yn, b.list_yn, b.align, b.group_seqFROM
(SELECT * FROM property_type WHERE ot_id = #otId# AND list_yn = '1') b LEFT OUTER JOIN
(SELECT * from property where ot_id = #otId# AND obj_id = '') a ON a.ot_id = b.ot_id AND a.pt_id = b.pt_id ORDER BY b.pt_order
This case statement is not legitimate:
case when length(a.prop_value1) > 18 then '...' else '' end ELSE a.prop_value1
I am not exactly sure what is the objective, but here are options that will fix it.
Either this is part of the ongoing case statement (i.e. the previous one) -- In this case, you don't need to write case again. It will continue from 'when length(a.prop_value1) > 18 then '...' else '' end ELSE a.prop_value1 '
If you want this to be a separate case statement altogether, you need to end the previous case statement by writing END before this case block begins (not to forget writing else part if you intend to.)
There are 2 else statements one after the other, that's again invalid either one of the else is part of the previous or following block.

If SCI.SOURCE="CC" , and SCI.CATEGORY should not be 'not awaiting'. I want to return the records based on this additional condition

SELECT DISTINCT sci.le_id AS le_id,
sci.sub_profile_id AS sub_profile_id,
sci.GROUP_ID AS GROUP_ID,
sci.cdd_id,
sci.crm_id,
sci.grp_crm_id,
sci.source,
sci.category
FROM table_name sci
WHERE sci.crm_id IN (SELECT master.x_ref_id
FROM biz_master master, biz_pr_master pr
WHERE master.x_latest_txn_id = pr.x_txn_id
AND pr.x_leid IS NULL
AND pr.GROUP_ID IS NULL)
I'm thinking of something like CASE:
and sci.category <> case when sci.source = 'CC' then 'not awaiting'
else '???
end
Then add it in the WHERE clause as follows:
WHERE ......
AND (sci.source <> 'CC' -- this condition will be true for all other sci.source
OR sci.category <> 'not awaiting') -- This condition will be checked if sci.source = CC

Query timeout increased but script fails to execute

When i execute this script on my remote database it gives me query timeout error. I've increased the timeout on my database but still have this error. I've been told if i'm able to optimized the script to make it simple it might work.
SELECT TOP 8 MIN( CASE WHEN pic_alb_love.pic=users_pics.pic
AND pic_alb_love.email = 'try#mail.com' THEN 'User' ELSE 'Guest' END)AS answer_one,
MIN ( CASE WHEN favorites.pic=users_pics.pic AND favorites.email = 'try#mail.com' THEN 'good' ELSE 'Bad'
END)AS answer2,
(CASE WHEN RTRIM (users_pics.upload_type) = 'wow' THEN 'loaded' ELSE
CASE WHEN RTRIM (users_pics.upload_type)= 'hey' THEN 'added' ELSE
CASE WHEN RTRIM (users_pics.upload_type) = 'check' THEN 'Changed' END END END)as up_ans,
(CASE WHEN RTRIM (users_pics.upload_type) = 'sample1' THEN 'new' ELSE
CASE WHEN RTRIM (users_pics.upload_type) = 'sample2' THEN 'existing' ELSE
CASE WHEN RTRIM (users_pics.upload_type) = 'sample3' THEN 'Profile Picture' END END END) as exs,
COUNT(DISTINCT users_pics.pic) as total,RTRIM (users_pics.wardrobe) as wardrobe,
fname,users_pics.wardrobe,
MIN (make)as make,MIN (htags)as htags, RTRIM (profile.profile_id) as profile_id,
users_pics.email,profile.profile_pix, RTRIM (profile.gender) as gender,
users_pics.time_group,profile.fpage,up_user_id, MIN (u_pic_id) as u_pic_id, MIN (users_pics.pic) as pic
FROM users_pics
LEFT join profile on users_pics.email = profile.email
LEFT join favorites on users_pics.pic = favorites.pic
LEFT JOIN pic_alb_love on users_pics.pic = pic_alb_love.pic
left join friends on users_pics.email = friends.resp_email
WHERE req_email = 'try#mail.com' and pic_enable='enable' or pic_view='Public'
GROUP BY users_pics.upload_type,profile.fname,profile.profile_id,users_pics.wardrobe,
users_pics.email, profile.gender,users_pics.time_group,profile.profile_pix, profile.fpage,up_user_id
ORDER BY MIN (users_pics.u_pic_id) DESC
Increasing timeout can help, but you should also check if your query isn't blocked by others operations like INSERT/UPDATE or open transaction.
The easiest way is to install and use sp_whoisactive procedure.
Second you don't need to nest CASE like you did:
(CASE WHEN RTRIM (users_pics.upload_type) = 'wow' THEN 'loaded' ELSE
CASE WHEN RTRIM (users_pics.upload_type)= 'hey' THEN 'added' ELSE
CASE WHEN RTRIM (users_pics.upload_type) = 'check' THEN 'Changed' END END END)as up_ans,
to
CASE RTRIM (user_pics.upload_type)
WHEN 'wow' THEN 'loaded'
WHEN 'hey' THEN 'added'
WHEN 'check' THEN 'changed'
ELSE NULL /* or your value like 'unknown' */
END AS up_ans
Next thing: you RTRIM almost on every string value, you should sanitize your input during inserting, unless you need spaces/tabs/newline and so on.
This way your query won't need RTRIM and can utilize index if exists any.
/* New values */
INSERT INTO table_name(...) VALUES (LTRIM(RTRIM(value...)))
/* Existing ones */
UPDATE table_name
SET col = LTRIM(RTRIM(col))
SQL Parser will understand wall of text, human will need time to do it.
I know we can argue about code style but remember you write code for people. Good readable code allow you to spot errors earlier and it is a hell easier to maintain in the future for you and your successors:
1) One selected value one line
2) The same order in SELECT and GROUP BY
3) Aggregated columns at end
4) You can use aliases no need for fully qualified names
5) No ambiguous column names, always specify from which table
6) SQL syntax UPPER CASE
7) Allign your code
Your query in more human readable from:
SELECT TOP 8
[up_user_id] /* Always add from which table even if it is unique column name, because in future you may get ambigous column */
,[fname]
,[profile_id] = RTRIM(profile.profile_id)
,[up_ans] = CASE RTRIM(users_pics.upload_type)
WHEN 'wow' THEN 'loaded'
WHEN 'hey' THEN 'added'
WHEN 'check' THEN 'changed'
ELSE NULL
END
,[exs] = CASE RTRIM(users_pics.upload_type)
WHEN 'sample1' THEN 'new'
WHEN 'sample2' THEN 'existing'
WHEN 'sample3' THEN 'Profile Picture'
ELSE NULL
END
,[wardrobe] = RTRIM(users_pics.wardrobe)
,users_pics.email
,[gender] = RTRIM(profile.gender)
,users_pics.time_group
,profile.profile_pix
,profile.fpage
,[answer_one] = MIN(CASE
WHEN pic_alb_love.pic=users_pics.pic THEN 'User'
ELSE 'Guest'
END)
,[answer2] = MIN(CASE
WHEN favorites.pic = users_pics.pic AND favorites.email = 'try#mail.com' WHEN 'good'
ELSE 'Bad'
END)
,[total] = COUNT(DISTINCT users_pics.pic)
,[make] = MIN(make)
,[htags] = MIN(htags)
,[u_pic_id] = MIN(u_pic_id)
,[pic] = MIN(users_pics.pic)
FROM users_pics /* you can use alias like AS up */
LEFT JOIN profile
ON users_pics.email = profile.email
LEFT JOIN favorites
ON users_pics.pic = favorites.pic
LEFT JOIN pic_alb_love
ON users_pics.pic = pic_alb_love.pic
LEFT JOIN friends
ON users_pics.email = friends.resp_email
WHERE
req_email = 'try#mail.com'
AND pic_enable = 'enable'
OR pic_view = 'Public'
GROUP BY
up_user_id
,profile.fname
,profile.profile_id
,users_pics.upload_type
,users_pics.wardrobe
,users_pics.email
,profile.gender
,users_pics.time_group
,profile.profile_pix
,profile.fpage
ORDER BY MIN(users_pics.u_pic_id) DESC
After you check that your query is not blocked during selecting data you can think about:
checking indexes on your tables
add WHERE condition to fetch smaller set, maybe you can use some update_date > current_date - 2 weeks
think to optimize query because now it does grouping and ordering which needs time to complete.
your WHERE condition, are you sure it shouldn't be:
.
WHERE (req_email = 'try#mail.com'
AND pic_enable = 'enable')
OR pic_view = 'Public'

Using case when - Is this possible?

Right off the bat - I'm quite new to 'case when'. I read the following: How do I perform an IF...THEN in an SQL SELECT? however it didn't really answer my question.
Essentially what I'm trying to do is something along the lines of the following:
select
section_name, *
from
property.lease_period lp
where
lp.lease_current_stop_date < getdate() and (lp.lease_status = 'Active' or lp.lease_status = 'Overholding')
and lp.period_id = #period_id
and lp.building_id = #building_id
and not exists
(
select 1
from lease_deal.lease
where lp.suite_name = tenancy_reference
and lp.building_id = building_id
)
case when(#section_name <> 'ALL')
then(and upper(section_name) = upper(#section_name))
end
order by period_id desc
Is this possible? If so what am I doing wrong?
Tl;dr:
Essentially I would like:
and upper(section_name) = upper(#section_name)
To only apply to my where clause when #section_name is not equal to 'ALL'
You just can change your (non-working) CASE to
AND (#section_name = 'ALL' OR upper(section_name) = upper(#section_name))
This can be done in a simpler way without the need to use CASE. It will be something like this:
and ((upper(section_name) = upper(#section_name) and #section_name <> 'ALL') OR #section_name ='ALL')
AND upper(section_name)=CASE WHEN #section_name <> 'ALL' THEN upper(#section_name)
ELSE upper(section_name)
END