Getting a missing keyword error in CASE WHEN statement - sql

I'm getting a missing keyword error in Oracle SQL and I'm not sure why. Here's my code. I want to have a column split by different times depending on the variable P1_DATE_CHOOSER. (I'm using Apex App Developer if that helps).
Select START_DATE,
Round(Avg(Run_TIME), 3) as "Average_RunTime",
Round(Max(Run_TIME), 3) as "Max_RunTime", Round(Median(Run_time), 3) as "Median_RunTime"
from
(Select job_id,
Case P1_DATE_CHOOSER
WHEN 'Daily' THEN TRUNC(start_time) as 'START_DATE'
WHEN 'Weekly' THEN to_char(start_time, 'WW') as 'START_DATE'
WHEN 'Monthly' THEN to_char(start_time, 'MONTH') as 'START_DATE'
END,
1440*(END_TIME - START_TIME)) as "RUN_TIME"
from NI_INFA_ACTIVITY_LOG_V
order by job_id asc, start_time asc)
group by START_DATE order by START_DATE
Any help would be appreciated.

Select START_DATE,
Round(Avg(Run_TIME), 3) as 'Average_RunTime',
Round(Max(Run_TIME), 3) as 'Max_RunTime',
Round(Median(Run_time), 3) as 'Median_RunTime'
from
(Select job_id,
(Case :P1_DATE_CHOOSER
WHEN 'Daily' THEN TRUNC(start_time)
WHEN 'Weekly' THEN to_char(start_time, 'DAY')
WHEN 'Monthly' THEN to_char(start_time, 'MONTH')
END) AS 'START_DATE',
1440*(END_TIME - START_TIME)) as "RUN_TIME"
from NI_INFA_ACTIVITY_LOG_V
)
group by START_DATE
order by START_DATE
;
First of all when ever you are binding the APEX variables or IDs, you have to
prefix with : followed by item ID.
Second, in case...when...then....end the column alias name must be mentioned after end key word.
Third, dont use group by order by inside the subqueries. No use if you do.

Your subquery needs an alias. If you want to do this:
select something
from
(subquery goes here)
You have to give it an alias
select something
from
(subquery goes here) aliasName
There are other issues with your code as well. The order by clause inside the subquery is useless at best.

Related

Dates in tables and charts are out of order in SQL

How am I able to display my results in order of date? I do have a order by clause but it does not seem to help. I am having the same issue when it is displayed on charts as well. Thanks in advance for your help.
select project_name, Dates, sum(records_number) as
from (
select project_name,
case
when :P22_DATE_RANGES = 'Monthly' then
to_char(date_sys, 'Month')
when :P22_DATE_RANGES = 'Daily' then
to_char(date_sys, 'DD-Mon-YYYY')
when :P22_DATE_RANGES = 'Weekly' then
to_char(TRUNC(date_sys, 'IW'), 'DD-Mon-YYYY')
end as Dates,
RECORDS_NUMBER
from BATCH
WHERE date_sys BETWEEN TO_DATE(:P22_START_DATE) AND TO_DATE(:P22_END_DATE)
) my_records
group by project_name, Dates
order by Dates ASC
;
You are ordering by Dates, but by that point it's a string, so string comparison rules apply - not real date comparison.
It looks like you need to check the required format twice, once for the inner query and then again to format as a string in the outer query; something like:
select project_name,
case
when :P22_DATE_RANGES = 'Monthly' then
to_char(Dates, 'Month')
else
to_char(Dates, 'DD-Mon-YYYY')
end as Dates,
sum(records_number) as
from (
select project_name,
case
when :P22_DATE_RANGES = 'Monthly' then
trunc(date_sys, 'MM')
when :P22_DATE_RANGES = 'Daily' then
trunc(date_sys, 'DD')
when :P22_DATE_RANGES = 'Weekly' then
trunc(date_sys, 'IW')
end as Dates,
RECORDS_NUMBER
from BATCH
WHERE date_sys BETWEEN TO_DATE(:P22_START_DATE) AND TO_DATE(:P22_END_DATE)
) my_records
group by project_name, Dates
order by Dates ASC
;
In the inner query the date_sys value is now being truncated, to IW as you already had, or to the day with DD (in case you have non-midnight times), or to the start of the month with MM.
In the outer query that truncated date is used for grouping and ordering, and is formatted as you require.
Incidentally, the Month and Mon format models are NLS-sensitive, so they will be shown in the session's date language. That may not be an issue, or may be what you want; but if not you can specify that they should always be shown in English, say, with:
select project_name,
case
when :P22_DATE_RANGES = 'Monthly' then
to_char(Dates, 'Month', 'nls_date_language=English')
else
to_char(Dates, 'DD-Mon-YYYY', 'nls_date_language=English')
end as Dates,
...
It seems a bit odd that your 'Monthly' format doesn't include the year - but not sure if that is intentional.

Druid SQL group by date

I'm writing an SQL query for Apache Druid and I would like to group results by date. I'm used to DB2 and I would typically do something like:
SELECT DATE(TIMESTAMP), COUNT(*) FROM my_table GROUP BY (DATE(TIMESTAMP))
I'm using the /druid/v2/sql API endpoint and passing in the query in a POST. I get an SQL parsing error when I try this. I know that I can group by day with something like
SELECT EXTRACT(day FROM timestamp), COUNT(*) FROM my_table GROUP BY 1
but I would like the full date if possible.
Thanks in advance.
Does this work?
SELECT DATE_TRUNC('day', TIMESTAMP), COUNT(*)
FROM my_table
GROUP BY DATE_TRUNC('day', TIMESTAMP);
Druid houses timeseries data having __time as PK.
Following SQL script in Druid might work grouping data Year, Month, Day wise.
SELECT TIME_EXTRACT(__time, 'DAY') AS dt, TIME_EXTRACT(__time, 'MONTH') AS mn, TIME_EXTRACT(__time, 'YEAR') AS yr, COUNT(1) AS cnt
FROM <datasource_name/table_name>
WHERE __time BETWEEN '<start_datetime>' and '<end_datetime>'
GROUP BY TIME_EXTRACT(__time, 'DAY'), TIME_EXTRACT(__time, 'MONTH'), TIME_EXTRACT(__time, 'YEAR')
HAVING cnt >= <Threshold_Value>
ORDER BY yr, mn, dt, cnt DESC

SQL query not retrieving data

SELECT DISTINCT
TO_CHAR(CREATION_DATE,'MONTH') creation_month
FROM
AP_INVOICES_ALL;
This query retrieves the month properly. But if I pass the month in where clause it doesn't retrieve data.
SELECT DISTCINT
TO_CHAR(CREATION_DATE, 'MONTH') CREATION_MONTH
FROM
AP_INVOICES_ALL
WHERE
TO_CHAR(CREATION_DATE, 'MONTH') = 'MARCH';
Please assist. I need to pass month as parameter in one report.
This is a known issue with 'MONTH' formats. The string is padded with characters.
Instead, use 'MON'. Check this out:
select to_char(sysdate, 'MONTH'),
(case when to_char(sysdate, 'MONTH')= 'APRIL' then 1 else 0 end),
to_char(sysdate, 'MON'),
(case when to_char(sysdate, 'MON')= 'APR' then 1 else 0 end)
from dual;
The first case expression returns 0 -- no match. The second returns 1, indicating that they do match.
I think passing in just the month, without the year, is not a good idea. And you will be far better off treating dates as dates, comparing them to dates, etc. Might I suggest something like the following?
SELECT TO_CHAR(creation_date, 'MONTH') AS creation_month
FROM ap_invoices_all
WHERE TRUNC(creation_date, 'MONTH') = DATE'2018-03-01';
TRUNC()ing the date to the month will return a value of type DATE of the first of the month at midnight. You can then compare using regular Oracle DATE values or ANSI DATE literals as above.
Hope this helps.

SQL Missing Right Parenthesis in nested PL/SQL Query

Can anyone help me out. I'm trying to take the date from one table and insert that into another, then base off the date if it's a weekend or weekday insert that string too. I've been able to do it separately so trying to do it in one swoop I've combined my expressions and now I get the notorious "missing right parenthesis.
Here's my block:
INSERT INTO time (sale_day, date_type)
SELECT sd, dt
FROM (
SELECT sale_date AS sd,(
case
when dy IS null or dy='' then 'Date Missing'
when dy='SAT' then 'Weekend'
when dy='SUN' then 'Weekend'
else 'Weekday' END) as date_type
FROM (SELECT TO_CHAR((sale_date), 'DY') AS dy FROM sales) AS dt
FROM sales
);
Thanks in advance!
Your query is far too complicated. There is no need for nesting three levels of select.
INSERT INTO time (sale_day, date_type)
SELECT sale_date AS sd,
case
when sale_date IS null then 'Date Missing'
when TO_CHAR(sale_date, 'DY') in ('SAT', 'SUN') then 'Weekend'
else 'Weekday'
END as date_type
FROM sales;
Unrelated, but: why are you copying that data into a new table? The query is extremely simple, and it would be more efficient if you just created a view for that information:
create or replace view time
as
SELECT sale_date AS sd,
case
when sale_date IS null then 'Date Missing'
when TO_CHAR(sale_date, 'DY') in ('SAT', 'SUN') then 'Weekend'
else 'Weekday'
END as date_type
FROM sales;
That way the information in time is always up-to-date without the need to copy data around.

Oracle date function for the previous month

I have the query below where the date is hard-coded. My objective is to remove the harcoded date; the query should pull the data for the previous month when it runs.
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and TRUNC(CREATION_DATE) BETWEEN '01-AUG-2012' AND '31-AUG-2012'
Should I use sysdate-15 function for that?
Modifying Ben's query little bit,
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and creation_date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1))
The trunc() function truncates a date to the specified time period; so trunc(sysdate,'mm') would return the beginning of the current month. You can then use the add_months() function to get the beginning of the previous month, something like this:
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and creation_date >= add_months(trunc(sysdate,'mm'),-1)
and creation_date < trunc(sysdate, 'mm')
As a little side not you're not explicitly converting to a date in your original query. Always do this, either using a date literal, e.g. DATE 2012-08-31, or the to_date() function, for example to_date('2012-08-31','YYYY-MM-DD'). If you don't then you are bound to get this wrong at some point.
You would not use sysdate - 15 as this would provide the date 15 days before the current date, which does not seem to be what you are after. It would also include a time component as you are not using trunc().
Just as a little demonstration of what trunc(<date>,'mm') does:
select sysdate
, case when trunc(sysdate,'mm') > to_date('20120901 00:00:00','yyyymmdd hh24:mi:ss')
then 1 end as gt
, case when trunc(sysdate,'mm') < to_date('20120901 00:00:00','yyyymmdd hh24:mi:ss')
then 1 end as lt
, case when trunc(sysdate,'mm') = to_date('20120901 00:00:00','yyyymmdd hh24:mi:ss')
then 1 end as eq
from dual
;
SYSDATE GT LT EQ
----------------- ---------- ---------- ----------
20120911 19:58:51 1
Data for last month-
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and to_char(CREATION_DATE,'MMYYYY') = to_char(add_months(trunc(sysdate),-1),'MMYYYY');
I believe this would also work:
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where
dealer_name = 'XXXX'
and (creation_date BETWEEN add_months(trunc(sysdate,'mm'),-1) and trunc(sysdate, 'mm'))
It has the advantage of using BETWEEN which is the way the OP used his date selection criteria.
It is working with me in Oracle sql developer
SELECT add_months(trunc(sysdate,'mm'), -1),
last_day(add_months(trunc(sysdate,'mm'), -1))
FROM dual
Getting last nth months data retrieve
SELECT * FROM TABLE_NAME
WHERE DATE_COLUMN BETWEEN '&STARTDATE' AND '&ENDDATE';