SQL Grouping Help Needed - sql

Depending on the 'INSP_CTGRY_CD' it will have a different metric on how long to complete.
I can see when the work was created, when it was completed, and the metric that I created code for. I would like to create a new column and group the results.
SELECT
A.INSP_CTGRY_CD, A.DT_WRKLD_CRTD,A.DT_INSP,
CASE
WHEN (A.INSP_CTGRY_CD IN
('a','b','c')) THEN 'a/b/c'
WHEN (A.INSP_CTGRY_CD IN
('d','e','f')) THEN 'd/e/f'
WHEN (A.INSP_CTGRY_CD IN
('g','h','i')) THEN 'g/h/i'
WHEN (A.INSP_CTGRY_CD IN
('j','k','l')) THEN 'j/k/l'
END AS Grouped_WRKLD_TYPE,
JULIAN_DAY (A.DT_INSP) - JULIAN_DAY (A.DT_WRKLD_CRTD) "AGE_DAYS",
CASE
WHEN (A.INSP_CTGRY_CD IN
('a','b','c')) THEN '5'
WHEN (A.INSP_CTGRY_CD IN
('d','e','f')) THEN '15'
WHEN (A.INSP_CTGRY_CD IN
('g','h','i')) THEN '30'
WHEN (A.INSP_CTGRY_CD IN
('j','k','l')) THEN '30'
END AS #_of_Days_Metric,
JULIAN_DAY (A.DT_INSP) - JULIAN_DAY (A.DT_WRKLD_CRTD) -
CASE
WHEN (A.INSP_CTGRY_CD IN
('a','b','c')) THEN 5
WHEN (A.INSP_CTGRY_CD IN
('d','e','f')) THEN 15
WHEN (A.INSP_CTGRY_CD IN
('g','h','i')) THEN 30
WHEN (A.INSP_CTGRY_CD IN
('j','k','l')) THEN 30
END AS How_Late,
WHEN
JULIAN_DAY (A.DT_INSP) - JULIAN_DAY (A.DT_WRKLD_CRTD) -
CASE
WHEN (A.INSP_CTGRY_CD IN
('a','b','c')) THEN 5
WHEN (A.INSP_CTGRY_CD IN
('d','e','f')) THEN 15
WHEN (A.INSP_CTGRY_CD IN
('g','h','i')) THEN 30
WHEN (A.INSP_CTGRY_CD IN
('j','k','l')) THEN 30
< -4 THEN '-4+'
= -3 THEN '-3'
= -2 THEN '-2'
= -1 THEN '-1'
= 0 THEN '0'
> 0 THEN '>0'
END AS How_Late_Grouped,
Results in an error "illegal use of of <

Related

Return true/false based on elapsed time from SQL

Let's say we have an SQL query such as below
select now()-insert_time AS time_elapsed, *
from account
where enabled = true AND machine = 'one'
limit 1
is it possible to return a boolean column for now()-insert_time AS time_elapsed? I want it to be true if it's more than 4 hours, and false if it's less than 4 hours.
You can compare it directly in your query
select now()-insert_time AS time_elapsed,
now()-insert_time >= '4 hours' as status,
*
from account
where enabled = true
In generally, you put it in CASE expression for other value output
select now()-insert_time AS time_elapsed,
CASE
WHEN now()-insert_time >= '4 hours' THEN 'Greater than 4 hours'
ELSE 'Less than 4 hours'
END as status,
*
from account
where enabled = true
AND machine = 'one'
limit 1
Hopefully it will help you.

Is there a function that will take an existing series of values in oracle SQL for Apex and will make a trendline based on those values?

I would like to create a trendline based on the values returned from a query. The logic needs to be applicable for other cases of placing a trendlines on series in Oracle PLSQL with Apex.
My series has X values that are dates and Y values that are time values. Here is my query that outputs my dates and Y values:
Select
null link,
(START_DATE) label,
Round(Avg(Run_TIME),3) "Average Length"
from
(Select job_id,
(Case :P4_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END) "START_DATE",
1440*(END_TIME - START_TIME) "RUN_TIME"
from apps.NI_INFA_ACTIVITY_LOG_V#util.world
WHERE
(:P4_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
OR
:P4_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND
(1440*(END_TIME - START_TIME)) <= 5
OR
:P4_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND
(1440*(END_TIME - START_TIME)) <= 20
OR
:P4_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
OR
:P4_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)
AND
(INFA_TYPE_CODE = 'WORKFLOW')
AND
OBJECT_NAME = :P4_WORKFLOWNAMES
AND
(
:P4_Data_Volume_Chooser = 'Small' AND SUCCESS_SOURCE_ROWS < 100
OR
:P4_Data_Volume_Chooser = 'Medium' AND SUCCESS_SOURCE_ROWS > 99 AND SUCCESS_SOURCE_ROWS < 10000
OR
:P4_Data_Volume_Chooser = 'Large' AND SUCCESS_SOURCE_ROWS > 9999
OR
:P4_Data_Volume_Chooser NOT IN ('Small','Medium','Large')
)
)
WHERE START_DATE BETWEEN
(Case :P4_DATE_CHOOSER
WHEN 'Daily' THEN trunc(to_date(:P4_BEGIN_DATES, 'MM-DD-YY'))
WHEN 'Weekly' THEN trunc(to_date(:P4_BEGIN_DATES, 'MM-DD-YY'), 'WW')
WHEN 'Monthly' THEN trunc(to_date(:P4_BEGIN_DATES, 'MM-DD-YY'), 'MM') END)
AND
(Case :P4_DATE_CHOOSER
WHEN 'Daily' THEN trunc(to_date(:P4_END_DATE, 'MM-DD-YY'))
WHEN 'Weekly' THEN trunc(to_date(:P4_END_DATE, 'MM-DD-YY'), 'WW')
WHEN 'Monthly' THEN trunc(to_date(:P4_END_DATE, 'MM-DD-YY'), 'MM') END)
group by START_DATE
order by START_DATE
;
Ideally, I'd be able to use my existing query as the source for a new subquery.

Invalid Identifier error message on left outer join using subqueries

This query only works if i replace the top select columns with "*". I've been reading through the other questions that are similar to mine but i haven't been able to apply their logic to my situation. All of the subqueries are the same except that they change based on the state in the "where" clauses.
There are far more successes everyday. Failures and warnings don't happen happen everyday so they have some null values that I would like to make into 0's. I want all of the successes, warnings, and failures to be related to the a.Start_date.
Select a.START_DATE, a.Successes, b.START_DATE, b.Failures, c.START_DATE, c.WARNINGS
FROM
(
Select
(Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END) "START_DATE",
NVL(count(job_id),0) as "Successes"
from NI_INFA_ACTIVITY_LOG_V
where State = 1
and
(:P1_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
OR
:P1_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND
(1440*(END_TIME - START_TIME)) <= 5
OR
:P1_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND
(1440*(END_TIME - START_TIME)) <= 20
OR
:P1_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
OR
:P1_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)
group by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
order by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
) a
left outer join
(
Select
(Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END) "START_DATE",
nvl(count(job_id),0) as "Failures"
from NI_INFA_ACTIVITY_LOG_V
where State = 3
and
(:P1_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
OR
:P1_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND
(1440*(END_TIME - START_TIME)) <= 5
OR
:P1_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND
(1440*(END_TIME - START_TIME)) <= 20
OR
:P1_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
OR
:P1_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)
group by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
order by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
) b
on
a.START_DATE = b.START_DATE
left outer join
(
Select
(Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END) "START_DATE",
nvl(count(job_id),0) as "Warnings"
from NI_INFA_ACTIVITY_LOG_V
where State = 2
and
(:P1_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
OR
:P1_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND
(1440*(END_TIME - START_TIME)) <= 5
OR
:P1_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND
(1440*(END_TIME - START_TIME)) <= 20
OR
:P1_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
OR
:P1_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)
group by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
order by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
) c
on
a.START_DATE = c.START_DATE
ORDER BY
a.START_DATE
At the end, I would like to have the results be something like:
Start_Date Successes Warnings Failures
6/1/2015 5 0 3
........ 8 15 4
6/30/2015 9 1 0
You've used quoted identifiers for (some of) the aliases in your subqueries, so you have to quote those in the outer select too, and exactly match the case you used:
Select a.START_DATE, a."Successes",
b.START_DATE, b."Failures",
c.START_DATE, c."Warnings"
...
Quoted identifiers are a pain. If you want the column titles to be mixed-case you could use unquoted identifiers in the subqueries and apply a final quoted name in ther outer query as another alias; or let the client handle that display issue.
And since start_date is the join condition, you probably don't want all three references; and to get the zeros in the result set you'll need to NVL the failure and warning counts, so you might as well use unquoted identifiers anyway:
Select a.start_date "Start date", a."Successes",
nvl(b.failures, 0) "Failures", nvl(c.warnings, 0) "Warnings"
...
NVL(count(job_id),0) as successes
...
The NVL you already have around the count isn't doing anything though - it needs to be in the outer query instead as shown - because there is no start date value to group by if the count is null.
If the subqueries really are so similar you could simplify this to a single query level with three selective counts; something like:
Select to_char(Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END, 'MM/DD/YYYY') as "Start date",
count(case when State = 1 then job_id end) as "Successes",
count(case when State = 3 then job_id end) as "Failures",
count(case when State = 2 then job_id end) as "Warnings"
from NI_INFA_ACTIVITY_LOG_V
where (:P1_JOB_SIZE_CHOOSER = 'Tiny'
AND (1440*(END_TIME - START_TIME)) <= 1)
OR (:P1_JOB_SIZE_CHOOSER = 'Small'
AND (1440*(END_TIME - START_TIME)) > 1
AND (1440*(END_TIME - START_TIME)) <= 5)
OR (:P1_JOB_SIZE_CHOOSER = 'Medium'
AND (1440*(END_TIME - START_TIME)) > 5
AND (1440*(END_TIME - START_TIME)) <= 20)
OR (:P1_JOB_SIZE_CHOOSER = 'Large'
AND (1440*(END_TIME - START_TIME)) > 20)
OR (:P1_JOB_SIZE_CHOOSER NOT IN ('Small','Medium','Large','Tiny')
AND (1440*(END_TIME - START_TIME)) > 0)
group by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END
order by Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN trunc(start_time)
WHEN 'Weekly' THEN trunc(start_time, 'WW')
WHEN 'Monthly' THEN trunc(start_time, 'MM')
END;
Your parentheses seem to be out of whack too, so I've attempted to correct those, but you may have been doing something intentional I didn't follow...
Replace
Select a.START_DATE, a.Successes, b.START_DATE, b.Failures, c.START_DATE, ...
by
Select a."START_DATE", a."Successes", b."START_DATE", b."Failures", c."START_DATE", ...

SQL Server: how to use manually defined column name for case statement

I am using the following Select as part of a bigger query.
Can someone here tell me how I can refer to the manually defined name "amountUSD" in my Case statement ?
I am always getting the following error when trying to save it this way:
"Invalid column name 'amountUSD'."
A work-around would probably be to insert it into a temp table first but I was hoping I could avoid that.
SELECT (CASE WHEN R.currency = 'USD' THEN '1' ELSE E.exchange_rate END) AS exchangeRate,
(R.amount * E.exchange_rate) AS amountUSD,
(
CASE WHEN amountUSD < 1000 THEN '18'
WHEN amountUSD < 5000 THEN '25'
WHEN amountUSD < 20000 THEN '27'
WHEN amountUSD < 100000 THEN '28'
WHEN amountUSD < 250000 THEN '29'
WHEN amountUSD < 2000000 THEN '30'
WHEN amountUSD < 5000000 THEN '31' END
) AS approvalLevel
FROM Exchange_Rates E
WHERE E.from_currency = R.currency
AND E.to_currency = 'USD'
FOR XML PATH(''), ELEMENTS, TYPE
Many thanks for any help with this, Tim.
You can not - because amountUSD does not exist at this point. It only exists in the output projection. You have 2 choices:
Not use amountUSD or
Not use your table, but make a 2 step query, first project amountUSD, THEN select over that and make the case there (approvalLevel).
This is not as hard as it sounds as you can make a select over another select.
Will this work?
SELECT (CASE WHEN R.currency = 'USD' THEN '1' ELSE E.exchange_rate END) AS exchangeRate,
(R.amount * E.exchange_rate) AS amountUSD,
(
CASE WHEN (R.amount * E.exchange_rate) < 1000 THEN '18'
WHEN (R.amount * E.exchange_rate) < 5000 THEN '25'
WHEN (R.amount * E.exchange_rate) < 20000 THEN '27'
WHEN (R.amount * E.exchange_rate) < 100000 THEN '28'
WHEN (R.amount * E.exchange_rate) < 250000 THEN '29'
WHEN (R.amount * E.exchange_rate) < 2000000 THEN '30'
WHEN (R.amount * E.exchange_rate) < 5000000 THEN '31' END
) AS approvalLevel
FROM Exchange_Rates E
WHERE E.from_currency = R.currency
AND E.to_currency = 'USD'
FOR XML PATH(''), ELEMENTS, TYPE
The reason why amountUSD is not available in the SELECT list, is because of the Logical Order of Query Processing: http://tsql.solidq.com/books/insidetsql2008/Logical%20Query%20Processing%20Poster.pdf
I believe the below code is one of the possible solutions that will work as described by TomTom.
SELECT *
,(CASE WHEN amountUSD < 1000 THEN '18'
WHEN amountUSD < 5000 THEN '25'
WHEN amountUSD < 20000 THEN '27'
WHEN amountUSD < 100000 THEN '28'
WHEN amountUSD < 250000 THEN '29'
WHEN amountUSD < 2000000 THEN '30'
WHEN amountUSD < 5000000 THEN '31' END
) AS approvalLevel
FROM
(
SELECT (CASE WHEN R.currency = 'USD' THEN '1' ELSE E.exchange_rate END) AS exchangeRate,
(R.amount * E.exchange_rate) AS amountUSD,
FROM Exchange_Rates E
WHERE E.from_currency = R.currency
AND E.to_currency = 'USD'
) t
FOR XML PATH(''), ELEMENTS, TYPE

How to get percentage in oracle?

I'm having a problem in my query. I can't get the percentage, no matter how i try. Please help me. I need to get the percent create and close time of POS and NON-POS weekly in individual query. I've always get an error. Thanks!
Query:
For POS:
SELECT 'Data'
||','||COUNT(CASE WHEN UPPER(TICKET_CUSTOMER_USER_ID) = UPPER('POS-generic') THEN 1 ELSE NULL END) --POS
FROM APP_ACCOUNT.OTRS_TICKET
WHERE TRUNC(CREATE_TIME, 'IW') BETWEEN SYSDATE -119 AND SYSDATE -1
AND trunc(CLOSE_TIME, 'IW') BETWEEN SYSDATE -119 AND SYSDATE -1;
For NON POS
SELECT 'Data'
||','||COUNT(CASE WHEN UPPER(TICKET_CUSTOMER_USER_ID) = UPPER('hcphuser') THEN 1 ELSE NULL END) --NON_POS
FROM APP_ACCOUNT.OTRS_TICKET
WHERE TRUNC(CREATE_TIME, 'IW') BETWEEN SYSDATE -119 AND SYSDATE -1
AND trunc(CLOSE_TIME, 'IW') BETWEEN SYSDATE -119 AND SYSDATE -1;
Some output of database:
Name ticket_customer_id create_time close_time
--------------------------------------------------------------------------
Cannot access the Zimbra Email POS-generic 10/15/2013 10/15/2013
Slow WIFI Connection POS-generic 10/15/2013 10/16/2013
Change phone number hcphuser 10/17/2013 10/18/2013
Output sample need:
FOR POS
Data, 10/10/2013, 50, 60%
Data, 10/17/2013, 30, 40%
FOR NON POS
Data, 10/10/2013, 70, 60%
Data, 10/17/2013, 50, 40%
I think you need an inner select.. Try this
SELECT 'Data', POS, NON_POS, ROUND((POS*100 / (NON_POS + POS)),2) NON_POS_PERCENTAGE, 100 - ROUND((POS*100 / (NON_POS + POS)),2) POS_PERCENTAGE
FROM (
SELECT 70 POS,
30 NON_POS
FROM DUAL
)
SELECT 'Data', POS, NON_POS, ROUND((POS*100 / (NON_POS + POS)),2) NON_POS_PERCENTAGE, 100 - ROUND((POS*100 / (NON_POS + POS)),2) POS_PERCENTAGE
FROM (
SELECT COUNT(CASE WHEN UPPER(TICKET_CUSTOMER_USER_ID) = UPPER('POS-generic') THEN 1 ELSE NULL END) POS,
COUNT(CASE WHEN UPPER(TICKET_CUSTOMER_USER_ID) = UPPER('hcphuser') THEN 1 ELSE NULL END) NON_POS
FROM APP_ACCOUNT.OTRS_TICKET
WHERE TRUNC(CREATE_TIME, 'IW') BETWEEN SYSDATE -119 AND SYSDATE -1
AND trunc(CLOSE_TIME, 'IW') BETWEEN SYSDATE -119 AND SYSDATE -1
)