Dates in tables and charts are out of order in SQL - 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.

Related

Case When in SQL , Two Different Attributes

New to the forum. I am looking to use a CASE WHEN function based on two separate fields . Those fields are order day and Month . Month is a calculation from:
DATEPART (Month, order_day ) AS Month
The code I have is below, but not getting the desired result. Want to say when order day is between x dates, then have the data in the Month column 1, otherwise give me the normal data that appears in the Month column.
when order_day between to_date ('20201227', 'YYYYMMDD') and TO_DATE ('20201231', 'YYYYMMDD') THEN Month = '1'
else Month End As Month2
Not easy to understand the question, but your case when in a SELECT statement should look like this:
SELECT
case when order_day between to_date ('20201227', 'YYYYMMDD') and TO_DATE('20201231', 'YYYYMMDD')
then Month = '1'
else Month
end

ORA-01839: date not valid for month specified, How to avoid leap year issues

I have a table that stores a valid "custom date" for each person. That date may legitimately be Feb 29 of a leap year. The thing is in my SQL for my report I need to pull the "last" mm/dd for from this custom date field for that employee as of the most recent year. This date is never in the future so I can compare the year in the date and if its the current year pull it as is. However if it's any previous year (can go back as far as 1900) I need to instead pull that MM/DD and as of last year. So you can see how this will be a problem since there is no Feb-29-2018.
I'm looking for the best solution on how to handle this. I need it in my select portion and my conditional block where this date I'm trying to derive has to be >= the applydtm date. Here is a sample query to replicate the error. Simply switching the Feb-29 date to Feb-28 will show it working since it doesn't encounter that invalid leap year date. I would be okay with all Feb 29 dates 'converting' to Mar 1st if need be as long as the code is efficient as possible. DB = Oracle 11g
WITH sampledata (actualcustomdtm, textfield, applydtm) AS (
SELECT
TO_DATE('02/29/2012 00:00:00','mm/dd/yyyy hh24:mi:ss'),
'Leap Year',
sysdate
FROM dual
UNION
SELECT
TO_DATE('01/15/2019 00:00:00','mm/dd/yyyy hh24:mi:ss'),
'Non-Leap Year',
sysdate
FROM dual
)
SELECT
actualcustomdtm,
CASE WHEN TO_CHAR(actualcustomdtm, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(actualcustomdtm, 'MM/DD/YYYY')
ELSE TO_CHAR(actualcustomdtm, 'MM/DD')||'/'||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -12), 'YYYY')
END AS "LASTACTCSTMDATE",
textfield,
applydtm
FROM sampledata
WHERE applydtm >=
TO_DATE(CASE WHEN TO_CHAR(actualcustomdtm, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(actualcustomdtm, 'MM/DD/YYYY')
ELSE TO_CHAR(actualcustomdtm, 'MM/DD')||'/'||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -12), 'YYYY')
END, 'MM/DD/YYYY')
I believe this logic does what you want -- getting the most recent anniversary up to or including today's date:
select dte, add_months(dte, 12),
(case when to_char(dte, 'MMDD') > to_char(sysdate, 'MMDD')
then add_months(dte, 12 * (extract(year from sysdate) - extract(year from dte) - 1))
else add_months(dte, 12 * (extract(year from sysdate) - extract(year from dte)))
end)
from (select date '2016-02-29' as dte from dual union all
select date '2018-01-03' from dual
) x;

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.

How to get Year and Month of a DATE using Oracle

How can I get the year and month of a date in the where clause using Oracle.
I used to be working with SQL server and it was as simple as YEAR(FIELDNAME) and MONTH(FIELDNAME).
I have tried the following:
SELECT *
FROM myschema.mytablename
WHERE EXTRACT(YEAR FROM myDATE) = 2017
however it gives ORA-30076 Error
Have you tried EXTRACT()?
SELECT EXTRACT(YEAR FROM DATE '2017-12-01') FROM DUAL;
2017
SELECT EXTRACT(MONTH FROM DATE '2017-12-01') FROM DUAL;
12
I tried this in sql fiddle with 11g and it works in WHERE clause too.
http://sqlfiddle.com/#!4/fb2b09/2
SELECT *
FROM myschema.mytablename
WHERE TO_CHAR(myDATE, 'YYYY') = '2017';
Explicitly convert year part of DATE into CHAR and compare it with literal.
For year and month comparison:
SELECT *
FROM myschema.mytablename
WHERE TO_CHAR(myDATE, 'YYYY') = '2017' AND TO_CHAR(myDate, 'MM') = '07';
Your query should work, but a better alternative would be
SELECT *
FROM YOUR_TABLE
WHERE MY_DATE BETWEEN TO_DATE('01-JAN-2017', 'DD-MON-YYYY')
AND TO_DATE('01-JAN-2018', 'DD-MON-YYYY') - INTERVAL '1' SECOND
Best of luck.
I did this with the function EXTRACT() and it works good for me.
I'm gonna share the query code here:
SELECT extract(YEAR from s.CREATE_DATE) as YEAR, extract(MONTH from s.CREATE_DATE) as MONTH, s.SALES_PERSON_GID, COUNT(s.SALES_ORDER_ID) as "TOTAL ORDERS" FROM SALES_ORDERS s, SALES_ORDER_STATUS ss WHERE s.SALES_ORDER_ID = ss.SALES_ORDER_ID and ss.STATUS_TYPE_ID = 'SALE ORDER STATUS' and ss.STATUS_VALUE_GID = 'SALE ORDER STATUS_DELIVERED' GROUP BY s.SALES_PERSON_GID,s.CREATE_DATE

Getting a missing keyword error in CASE WHEN statement

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.