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

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.

Related

Hive query to find conversion ratio

I am trying this query in Hive and it's not working.
select
(
(
select
count(*)
from
click_streaming
where
page_id= 'e7bc5fb2-1231-11eb-adc1-0242ac120002'
and is_page_view = 'Yes'
) / (
select
count(*)
from
click_streaming
where
button_id= 'fcba68aa-1231-11eb-adc1-0242ac120002'
and is_button_click= 'Yes'
)
) as conversion_ratio;
Error I am getting: cannot recognize input near 'select' 'count' '(' in expression specification
I am basically trying to get conversion rate of customers who view the page and click the button to book a cab.
This is not how the syntax can be. Just join them both or use a case when to do your job.
select
sum(case when page_id= 'e7bc5fb2-1231-11eb-adc1-0242ac120002' and is_page_view = 'Yes' then 1 else 0 end) /
sum(case when button_id= 'fcba68aa-1231-11eb-adc1-0242ac120002' and is_button_click= 'Yes' then 1 else 0 end) conv_ratio
FROM
click_streaming
or you can reuse your SQLs but you got to join them
select c1/c2
from (
select
count(*) c1
from
click_streaming
where
page_id= 'e7bc5fb2-1231-11eb-adc1-0242ac120002'
and is_page_view = 'Yes') rs
join (select
count(*) c2
from
click_streaming
where
button_id= 'fcba68aa-1231-11eb-adc1-0242ac120002'
and is_button_click= 'Yes')rs2

Why Would Unknown Column Be Referenced in SQL Query

I am in the process of updating some SQL queries to run against MariaDB instead of via SQL Anywhere. One query I'm running is erroring with this:
Error Code: 1054. Unknown column 'choice' in 'field list'
That is for this query:
SELECT
(select firstname||' '||lastname||' ('||service||')' from staff_members where id_number = customer_assignment_reviews.staff_member_id) as Rep,
(select customer_firstname||' '|| customer_lastname from customers where id_number = customer_assignment_reviews.cs_id) as Cus,
last_modified as "Response Date",replace(review_reason,'’','') as "Reason",
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
FROM customer_assignment_reviews
where staff_member_id in (Select id_number from kar.staff_members where division_id = 6)
and "Response Date" between today() - 7 and today() /* Date Range */
and "Accepted?" = 'No'
Order by 3 desc
Is this error message as straightforward as it sounds? It's simply saying the column "choice" doesn't exist on the target table?
I'm just trying to reason through why this code (which I inherited) would be referencing a column that does not exist. Could something be expected here at runtime?
You don't need to use subquery in SELECT list
SELECT
-- ...
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
=>
SELECT
CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end as "Accepted?"
Additionaly syntax SELECT alias = expression is only T-SQL specific:
SELECT alias = 1
<=>
SELECT 1 AS alias
What is this supposed to mean?
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
Very importantly, a select is not needed here. You might mean:
(case when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as is_accepted -- prefer to not have to need escape characters
If accepted only takes those two values, you can simplify this to:
elt(accepted + 1, 'No', 'Yes') as is_accepted

case or if else in a where clause Sql Server

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 )
)

syntax error case statement

I am trying to write an sql statement but i am getting syntax error. I know it is do with my select and case statement but cant figure out.As the error is not descriptive. I am using redshift
select school_district_teacher_ind,customer_status,initial_pay_type,(select(
CASE
WHEN total_line_price = 0
THEN 'free'
ELSE 'paid'
END
)
from storiacloud.schl_storia_revenue_fact_a)as a,count(distinct convert(varchar(100),[Otc_Order_Number])+'_'+ convert(varchar(100),[Otc_Order_Line_Number]))
from storiacloud.schl_storia_revenue_fact_a as fact
inner join
storiacloud.schl_storia_school_status as status
on fact.school_ucn = status.ucn
where date = '11/2/2015'
group by school_district_teacher_ind,customer_status,initial_pay_type,a
Below is the error
ERROR: Invalid Query:
Detail:
-----------------------------------------------
error: Invalid Query:
code: 8001
context: single-row subquery returns more than one row
query: 5132289
location: 25.cpp:69
process: padbmaster [pid=29183]
-----------------------------------------------
Execution time: 0.16s
1 statement failed.
The results that i expect are
Note first column customer type is school_district_teacher_ind in the above select statment
Your case was a subquery that is selecting from the same table as your main query. Try this;
SELECT school_district_teacher_ind ,
customer_status ,
initial_pay_type ,
CASE WHEN total_line_price = 0 THEN 'free'
ELSE 'paid'
END AS a ,
COUNT(DISTINCT CONVERT(VARCHAR(100), [Otc_Order_Number]) + '_'
+ CONVERT(VARCHAR(100), [Otc_Order_Line_Number]))
FROM storiacloud.schl_storia_revenue_fact_a AS fact
INNER JOIN storiacloud.schl_storia_school_status AS status ON fact.school_ucn = status.ucn
WHERE date = '11/2/2015'
GROUP BY school_district_teacher_ind ,
customer_status ,
initial_pay_type ,
CASE WHEN total_line_price = 0 THEN 'free'
ELSE 'paid'
END
I think you just want conditional aggregation. The query is something like this:
select school_district_teacher_ind, customer_status, initial_pay_type,
sum(case when total_line_price = 0 then 1 else 0 end) as free,
sum(case when total_line_price = 0 then 0 else 1 end) as paid
from storiacloud.schl_storia_revenue_fact_a fact inner join
storiacloud.schl_storia_school_status status
on fact.school_ucn = status.ucn
where date = '2015-11-02'
group by school_district_teacher_ind,customer_status, initial_pay_type;

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'