Im trying to filter results by a specific date but when I use the below code I only get results where CloseDate matches current date. It doesnt include the results from ResolvedDate when CloseDate is Null.
I tried with :
(CASE WHEN (Closedate IS Null) then ResolvedDate, ELSE CloseDate END) AS FinalDate
but then it states:
"column FinalDate does not exist"
Any other way I can do this?
Here is the code thus far. Appreciate your help.
SELECT
id,
(CASE WHEN (Closedate IS Null) then ResolvedDate, ELSE CloseDate END),
FROM cases
WHERE (EXTRACT (month FROM Closedate) = EXTRACT(month FROM current_date))
AND ( EXTRACT(day from Closedate) = EXTRACT(day FROM current_date))
Assuming you want to match the year as well:
SELECT id, COALESCE(Closedate, ResolvedDate) AS cdate
FROM cases
WHERE date_trunc('day', COALESCE(Closedate, ResolvedDate))
= date_trunc('day', now())
Per documentation: COALESCE, date_trunc()
If you want to ignore the year:
WHERE to_char(COALESCE(Closedate, ResolvedDate), 'MMDD')
= to_char(now(), 'MMDD')
A bit more on that:
How do you do date math that ignores the year?
You should use COALESCE function http://www.postgresql.org/docs/current/static/functions-conditional.html
Try this:
SELECT
id,
COALESCE(CloseDate, ResolvedDate) AS FinalDate
FROM
cases
WHERE
(EXTRACT (month FROM COALESCE(CloseDate, ResolvedDate)) = EXTRACT(month FROM current_date)) AND
(EXTRACT (day from COALESCE(CloseDate, ResolvedDate)) = EXTRACT(day FROM current_date))
That should do it...
Related
With PostgreSQL, while using the AGE() function to display age from date of birth in my table, with query
SELECT date_of_birth, AGE(NOW(), date_of_birth) AS age FROM person;
Got the following,result.
I want to select only year and month from the timestamp, so the result be like "1 year 3 mons",
Tried using EXTRACT(),it outs only one field at a time,
SELECT date_of_birth, EXTRACT(YEAR FROM AGE(NOW(), date_of_birth)) AS age FROM person;
and, TO_CHAR(),
SELECT date_of_birth, TO_CHAR(AGE(NOW(), date_of_birth), 'YY-MM') AS age FROM person;
But the result is not in the desired format, can anyone please explain how to use the above methods in correct way or any other methods to get the desired result.
You can format the interval using TO_CHAR():
TO_CHAR(AGE(NOW(), date_of_birth), 'YY "Year" MM "month"') AS age
However, a more colloquial solution is to build the parts separately:
CONCAT_WS(' ',
(CASE WHEN EXTRACT(YEAR FROM v.age) = 0 THEN NULL
WHEN EXTRACT(YEAR FROM v.age) = 1 THEN '1 year'
ELSE EXTRACT(YEAR FROM v.age) || ' years'
END),
(CASE WHEN EXTRACT(MONTH FROM v.age) = 1 THEN '1 month'
ELSE EXTRACT(MONTH FROM v.age) || ' months'
END)
) as age
This handles things like "1 year" versus "2 years".
Here is a db<>fiddle.
For the query below, I'm trying to pull a specific date range depending on the current day of the month. If it's the 20th or less (e.g. "2/7/2020") then I want the date range for January. Otherwise, I want the date range for February. Is it possible to be done with a case statement? Or there is a better way?
SELECT
account,
start_date,
amount
FROM
table1
WHERE
CASE
WHEN (
SELECT
CAST(EXTRACT(DAY FROM sysdate) AS NUMBER)
FROM
dual
) <= 20 THEN
start_date
BETWEEN '2020-01-01' AND '2020-01-31'
ELSE start_date BETWEEN '2020-02-01' AND '2020-02-29'
END
You can do this by avoiding the case statement and using truncate the date - 20 to the month, e.g.:
SELECT account,
start_date,
amount
FROM table1
WHERE start_date >= TRUNC(SYSDATE - 20, 'mm')
AND start_date < add_months(TRUNC(dt - 20, 'mm'), 1);
If you really had to use a CASE expression (you can't use a CASE statement in SQL), you would need to do something like:
SELECT account,
start_date,
amount
FROM table1
WHERE start_date >= CASE WHEN to_char(SYSDATE, 'dd') <= '20' THEN add_months(TRUNC(SYSDATE, 'mm'), -1) ELSE TRUNC(SYSDATE, 'mm') END
AND start_date < CASE WHEN to_char(SYSDATE, 'dd') <= '20' THEN TRUNC(SYSDATE, 'mm') ELSE add_months(TRUNC(SYSDATE, 'mm'), 1) END;
N.B. if you're using a function, you don't need to wrap it in a select .. from dual, you can use it directly in the SQL statement.
I've also assumed that you want a dynamic range, e.g. if the day of the month is 20 or less, the range is for the previous month, otherwise the current month.
ETA: You would use the above two queries if there is an index on the start_date column, otherwise you could simply do:
SELECT account,
start_date,
amount
FROM table1
WHERE TRUNC(start_date, 'mm') = TRUNC(SYSDATE - 20, 'mm');
Case statements return single values. As such you should pull out the start date and you'll need two case statements.
select account, start_date, amount
from table1 where
start_date between
(case
when (select cast(extract(day from sysdate) as number) from dual) <= 20 then '2020-01-01'
else '2020-02-01'
end) and
(case
when (select cast(extract(day from sysdate) as number) from dual) <= 20 then '2020-01-31'
else '2020-02-29'
end)
One method subtracts 20 days and then gets the month boundary:
where start_date >= trunc(sysdate - interval '20' day, 'MON') and
start_date < trunc(sysdate - interval '20' day, 'MON') + interval '1' month
This approach is index (and partition) friendly -- an appropriate index on start_date can be used. It is also safe if start_date has time components.
Note: You can use sysdate without having to use a subquery.
You can use or operator with last_day function as following:
Select * from your_table
Where (
start_date <= trunc(sysdate,'mm') + 20
and start_date between trunc(sysdate,'mm') - interval '1' month and trunc(sysdate,'mm') - 1
)
Or
(
start_date > trunc(sysdate,'mm') + 20
and start_date between trunc(sysdate, 'mm') and last_day(sysdate)
)
This approach will use index on start_date, if any.
Cheers!!
select account, amount, start_date
from table1
where ( ( (select cast (extract (day from sysdate) as number) from dual) <= 20
and start_date between date '2020-01-01' and date '2020-01-31')
or ( (select cast (extract (day from sysdate) as number) from dual) > 20
and start_date between date '2020-02-01' and date '2020-02-29')
);
Using CASE expressions as BETWEEN operands:
SELECT account
, start_date
, amount
FROM table1
WHERE start_date BETWEEN CASE
WHEN extract(day from sysdate) <= 20
THEN trunc(sysdate -interval '1' month, 'month')
ELSE trunc(sysdate, 'month')
END
AND CASE
WHEN extract(day from sysdate) <= 20
THEN last_day(sysdate -interval '1' month)
ELSE last_day(sysdate)
END
I got a date that I want to find the all records in the past that got the same month and day.
The problem accrues when there is no such date in the same year. For example, the 29th February.
My goal is to get the nearest date from below the date that does not exist.
This is my currently query with the date 2012-02-29:
SELECT date, amount
FROM table_name
WHERE
EXTRACT(MONTH FROM date) = EXTRACT(MONTH FROM DATE('2012-02-29') )
AND EXTRACT(DAY FROM date) = EXTRACT(DAY FROM DATE('2012-02-29') )
AND date < '2012-02-29'
ORDER BY date DESC LIMIT 10;
If I understand correctly, you want one date per year with the property that that day is nearest to the given date.
I would suggest using distinct on:
select distinct on (date_trunc('year', date)) t.*
from table_name t
order by date_trunc('year', date),
abs(date_part('day, (date -
(date '2012-02-29' -
(extract(year from date '2012-02-29') - extract(year from date)) * interval '1 year'
)
)
)
)
);
EDIT:
An example of working code:
select distinct on (date_trunc('year', date)) t.*
from table_name t
order by date_trunc('year', date),
abs(date_part('day', date - (date '2012-02-29' -
((extract(year from date '2012-02-29') - extract(year from date)) * interval '1 year')
)
))
Requirement is input date should produce first day of the month.
Condtions are:
If the date entered is between 16-nov to 30-nov, then the first day will be 16-nov.
if the date entered is between 1-nov to 15-nov , then the first day will be 01-nov.
for all other month it should return 01st day of corresponding month.
Building on Tim Biegeleisen's solution, simplifying it and avoid the date-to-text-to-date conversions. Note the use of TRUNC to get the first date of the period.
SELECT
CASE
WHEN EXTRACT(MONTH FROM DATE_COL) = 11 AND EXTRACT(DAY FROM DATE_COL) >= 16
THEN TRUNC(DATE_COL, 'MONTH') + 15
ELSE TRUNC(DATE_COL, 'MONTH')
END AS FIRST_OF_MONTH
FROM T1
I used a lengthy CASE expression to handle this, containing the logic for the three cases you mentioned in your question.
SELECT CASE WHEN EXTRACT(month FROM date) = 11 AND
EXTRACT(day FROM date) >= 16
THEN TO_DATE(EXTRACT(year FROM date) || '-11-16', 'yyyy-mm-dd')
ELSE TO_DATE(EXTRACT(year FROM date) || '-' || EXTRACT(month FROM date) ||
'-01', 'yyyy-mm-dd')
END AS newDate
FROM yourTable
Hello All
I have a table in my pg admin database.There is an employee table in this table.Having the field:-
1)name
2)date_of_birth
Now the scenario is that I want to know the birth day for current date and upcoming 20 days
For example if current date is 28-Jan-2013 then
1)from_date=28-Jan-2013
2)to_date=16-feb-2013
I want to select all the records from the table for which the
date_of_birth
lies between 28-Jan and 16-feb
Try this:
SELECT *
FROM bdaytable
WHERE bdate >= '2013-01-28'::DATE
AND bdate <= '2013-02-16'::DATE;
You may also try overlaps:
SELECT *
FROM bdaytable
WHERE (bdate, bdate)
OVERLAPS ('2013-01-28'::DATE, '2013-02-16'::DATE);
with extract, month, day:
SELECT *
FROM bdaytable
WHERE Extract(month from bdate) >= Extract(month from '2013-01-28'::DATE)
AND Extract(month from bdate) <= Extract(month from '2013-02-16'::DATE)
AND Extract(day from bdate) >= Extract(day from '2013-01-28'::DATE)
AND Extract(day from bdate) <= Extract(day from '2013-02-16'::DATE);
Incorporating Now() and interval to make the query dynamic with current date:
SELECT *
FROM bdaytable
WHERE Extract(month from bdate) >= Extract(month from Now())
AND Extract(month from bdate) <= Extract(month from Now() + Interval '20 day')
AND Extract(day from bdate) >= Extract(day from Now())
AND Extract(day from bdate) <= Extract(day from Now() + Interval '20 day');
select *
from employee
where
to_char(date_of_birth, 'MMDD') between
to_char(current_date, 'MMDD') and to_char(current_date + 20, 'MMDD')
I think this should work. Use interval.
SELECT *
FROM Employee
WHERE Date_Of_Birth >= now() AND Date_Of_Birth <= now() + interval '20 day'
If you want to get any birth date between these days (and year doesn't matter), then that would be slightly different.
EDIT
If year doesn't matter, while I'm sure there is a better way, this could work. Basically it's just converting all years to a common year (in this case 2000) -- you could do the same with your input parameter as well.
(Date_Of_Birth + (2000-EXTRACT(YEAR FROM Date_Of_Birth) || ' years')::interval)
Curious what others have used in the past as this is probably not the most efficient.
Good luck.