Query timeout increased but script fails to execute - sql

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'

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.

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 Expression on a created column using Microsoft SQL

Within a view I put put together a select statement within a case and delcared it as a column. The column name is 'IR2'
How can I case off of the column 'IR2'?
I end up getting an error which says 'Invalid Column Name 'IR2'.
What are my work around options?
case when r.ana = 'nh3' and r.serv='energy' and exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa end as IR2,
CASE IR2 WHEN 'Released' then
''
ELSE
'*'
END AS IR
You can use a subquery or CTE. But another fun way in SQL Server is using outer apply:
select v.IR2,
(case IR2 when 'Released' then '' else '*' end) as ir
from . . . outer apply
(values (case when r.ana = 'nh3' and r.serv='energy' and
exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa
end)
) v(IR2)
CTE would be the best choice. If you want to continue with current statement, you need to put a copy of the case statement in other case statement. Very messy code.
SELECT
case when r.ana = 'nh3' and r.serv='energy' and
exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa end as IR2,
CASE
(case when r.ana = 'nh3' and r.serv='energy'
and exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa end)
WHEN 'Released' then
''
ELSE
'*'
END AS IR

How to refer to a previously computed value in SQL Query statement

I am trying to add a CASE statement to the end of my SQL query to compute a value depending upon another table value and a previously computed value in the SELECT. The error is returned that DelivCount is an invalid column name. Is there a better way to do this or am I missign something?
SELECT jd.FullJobNumber, jd.ProjectTitle, jd.ClientName, jd.JobManager, jd.ProjectDirector, jd.ServiceGroup, jd.Status, jd.HasDeliverables, jd.SchedOutsideJFlo, jd.ReqCompleteDate,(SELECT COUNT(*)FROM DeliverablesSchedule ds WHERE jd.FullJobNumber = ds.FullJobNumber) as DelivCount, SchedType =
CASE
WHEN (jd.SchedOutsideJFlo = 'Yes')
THEN 'outside'
WHEN (jd.HasDeliverables = 'No ')
THEN 'none'
WHEN (DelivCount > 0)
THEN 'has'
WHEN (jd.HasDeliverables = 'Yes' AND DelivCount = 0)
THEN 'missing'
ELSE 'unknown'
END
FROM JobDetail jd
try this
SELECT
Z.*,
SchedType =
CASE
WHEN (Z.SchedOutsideJFlo = 'Yes')
THEN 'outside'
WHEN (Z.HasDeliverables = 'No ')
THEN 'none'
WHEN (Z.DelivCount > 0)
THEN 'has'
WHEN (Z.HasDeliverables = 'Yes' AND Z.DelivCount = 0)
THEN 'missing'
ELSE 'unknown'
END
FROM
(
SELECT
jd.FullJobNumber,
jd.ProjectTitle,
jd.ClientName,
jd.JobManager,
jd.ProjectDirector,
jd.ServiceGroup,
jd.Status,
jd.HasDeliverables,
jd.SchedOutsideJFlo,
jd.ReqCompleteDate,
(SELECT COUNT(*)FROM DeliverablesSchedule ds WHERE jd.FullJobNumber = ds.FullJobNumber) as DelivCount
FROM JobDetail jd
)
Z
try this, which should run a lot faster:
SELECT
jd.FullJobNumber, jd.ProjectTitle, jd.ClientName, jd.JobManager, jd.ProjectDirector, jd.ServiceGroup, jd.Status, jd.HasDeliverables, jd.SchedOutsideJFlo, jd.ReqCompleteDate
,ds.DelivCount
,SchedType =CASE
WHEN (jd.SchedOutsideJFlo = 'Yes')
THEN 'outside'
WHEN (jd.HasDeliverables = 'No ')
THEN 'none'
WHEN (ds.DelivCount > 0)
THEN 'has'
WHEN (jd.HasDeliverables = 'Yes' AND ds.DelivCount = 0)
THEN 'missing'
ELSE 'unknown'
END
FROM JobDetail jd
LEFT OUTER JOIN (SELECT
FullJobNumber, COUNT(*) AS DelivCount
FROM DeliverablesSchedule
GROUP BY FullJobNumber
) ds ON jd.FullJobNumber = ds.FullJobNumber
The original query uses a subquery:
A subquery is a SELECT query that
returns a single value and is nested
inside a SELECT, INSERT, UPDATE, or
DELETE statement, or inside another
subquery. A subquery can be used
anywhere an expression is allowed.
by the very nature of a sub query, it must be run repeatedly, once for each row. I have rewritten the query to use a derived table, which is evaluated one time to find all of the counts and is then joined to the proper rows. This allows for the DelivCount value to be referred to as any column would be when joined from another table, and should speed up this query.