Here is how the date is formatted:
XXXXXX001221
This date is for Dec 21
If I want to get yesterdays entries using the CURDATE() function how would I do this?
If you're just doing month-day (indices are based on the string format of CURDATE(), which is YYYY-MM-DD):
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 6 FOR 2),
SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 9 FOR 2));
Or an alternative way using EXTRACT():
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
For year as well:
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 3 FOR 2),
SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 6 FOR 2),
SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 9 FOR 2));
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', EXTRACT(YEAR FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
EDIT: Instead of WHERE date_field LIKE ... you can use WHERE RIGHT(date_field, 6) = ... as mentioned in codethis' answer:
SELECT * FROM table_name
WHERE RIGHT(date_field, 4) =
CONCAT(EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
SELECT * FROM table_name
WHERE RIGHT(date_field, 6) =
CONCAT(EXTRACT(YEAR FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
NOTE: You can also use a variable to save calculating DATE_SUB(CURDATE(), INTERVAL 1 DAY) all the time.
SET #yesterday = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
SELECT ...
Try something like:
SELECT * FROM table WHERE RIGHT(date_col, 6) = (SELECT CONVERT(VARCHAR(6), GETDATE()-1, 12) AS [YYMMDD])
Related
Can we minimize this big case statement in simplified one.
case
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 1 MONTH)) then 12
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 2 MONTH)) then 11
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 3 MONTH)) then 10
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 4 MONTH)) then 9
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 5 MONTH)) then 8
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 6 MONTH)) then 7
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 7 MONTH)) then 6
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 8 MONTH)) then 5
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 9 MONTH)) then 4
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 10 MONTH)) then 3
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 11 MONTH)) then 2
when EXTRACT(MONTH from GIVEN_DATE) = EXTRACT(MONTH from DATE_SUB(CURRENT_DATE(), interval 12 MONTH)) then 1
end as MONTH_NUMBER
Consider below approach
select given_date, 1 + mod(extract(month from given_date) + 5, 12) as MONTH_NUMBER
If to apply to some dummy dates - output is
Are you looking for something like this?
select 1 + date_diff(current_date(), given_date, month)
This makes a lot of assumptions, such as given_date being within a year. If not, then modulo arithmetic probably does what you want:
select 1 + (date_diff(current_date(), given_date, month) % 12)
08-SEP-20 08:55:05
08-SEP-20 15:36:13
The query below is working correctly for 15:36:13 in that it rounds to 15:30 but the 8:55:05 is rounding down to 08:45 when it should be rounding to 09:00
select event_date,trunc(event_date,'mi') - numtodsinterval( mod(to_char(event_date,'mi'),15), 'minute' ) as nearest_quarter
from time_source_in_all where empno = '002307718' and event_date between '8-sep-2020' and '9-sep-2020'
I think this will do what you want:
select trunc(event_date, 'HH') + round(extract(minute from event_date) / 15) * interval '15' minute )
. . .
Note: I prefer the extract() because it is standard SQL. But it assumes that the column is a timestamp and not a date.
or the equivalent:
select trunc(event_date, 'HH') + numtodsinterval(round(to_number(to_char(event_date, 'MI')) / 15) * 15, 'minute')
You can use:
SELECT event_date,
TRUNC( event_date, 'HH' )
+ ROUND( EXTRACT( MINUTE FROM CAST( event_date AS TIMESTAMP ) ) / 15 )
* INTERVAL '15' MINUTE
AS rounded_15_event_date
FROM table_name
or:
SELECT event_date,
TRUNC( event_date, 'HH' )
+ ROUND( ( event_date - TRUNC( event_date, 'HH' ) ) * 24 * 4 )
* INTERVAL '15' MINUTE
AS rounded_15_event_date
FROM table_name
Which, for your sample data:
CREATE TABLE table_name ( event_date ) AS
SELECT DATE '2020-09-08' + INTERVAL '08:55:05' HOUR TO SECOND FROM DUAL UNION ALL
SELECT DATE '2020-09-08' + INTERVAL '15:36:13' HOUR TO SECOND FROM DUAL
Both output:
EVENT_DATE | ROUNDED_15_EVENT_DATE
:------------------ | :--------------------
2020-09-08 08:55:05 | 2020-09-08 09:00:00
2020-09-08 15:36:13 | 2020-09-08 15:30:00
db<>fiddle here
Does anyone have a easy solution to make a numbering from sunday to saturday and generate the dates in PostgreSQL(version 11).I have the below solution but it is limited to only 5 weeks and i need something that is flexible.
I have dates as a column in my source table, i want those dates to be numbered from saturday to sunday like below.
Current Query
WITH CTE AS
(
SELECT 1 as rno,generate_series( date_trunc('week', current_date)::date - 1
, date_trunc('week', current_date)::date + 5
, interval '1 day') current_week
)
,CTE_1 AS
(
SELECT rno,current_week FROM CTE
UNION
select 2,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE)- interval '1 days', interval '1 days') dt
)
,CTE_2 AS
(
SELECT rno,current_week FROM CTE_1
UNION
select 3,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE_1)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE_1)- interval '1 days', interval '1 days') dt
)
,CTE_3 AS
(
SELECT rno,current_week FROM CTE_2
UNION
select 4,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE_2)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE_2)- interval '1 days', interval '1 days') dt
)
,last_5_weeks as
(
SELECT rno,current_week FROM CTE_3
UNION
select 5,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE_3)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE_3)- interval '1 days', interval '1 days') dt
)
SELECT rno,current_week::DATE as selected_date FROM last_5_weeks order by selected_date DESC
Current output
rno Date
1 "2020-10-24"
1 "2020-10-23"
1 "2020-10-22"
1 "2020-10-21"
1 "2020-10-20"
1 "2020-10-19"
1 "2020-10-18"
2 "2020-10-17"
2 "2020-10-16"
2 "2020-10-15"
2 "2020-10-14"
2 "2020-10-13"
2 "2020-10-12"
2 "2020-10-11"
3 "2020-10-10"
3 "2020-10-09"
3 "2020-10-08"
3 "2020-10-07"
3 "2020-10-06"
3 "2020-10-05"
3 "2020-10-04"
4 "2020-10-03"
4 "2020-10-02"
4 "2020-10-01"
4 "2020-09-30"
4 "2020-09-29"
4 "2020-09-28"
4 "2020-09-27"
5 "2020-09-26"
5 "2020-09-25"
5 "2020-09-24"
5 "2020-09-23"
5 "2020-09-22"
5 "2020-09-21"
5 "2020-09-20"
How about using arithmetics?
select 1 + (row_number() over(order by dt desc) - 1) / 7 rn, dt::date dt
from generate_series(
date_trunc('week', current_date)::date + 5 - interval '5 week -1 day',
date_trunc('week', current_date)::date + 5,
'1 day'
) s(dt)
order by dt desc
generate_series() produces all dates at once. You control the number of weeks that are generated with the value given to week in the literal interval. Then, in the outer query, we use row_number() to enumerate the week numbers.
Demo on DB Fiddle
One sequence for weeks and another one for days. It is flexible, 5 is a parameter. date_trunc('week',now()+'P1W'::interval)::date-2 is this week's saturday.
select
w rno,
date (date_trunc('week',now()+'P1W'::interval)::date-2 + make_interval(weeks => 1-w, days => 1-d)) "Date"
from generate_series(1, 5, 1) w
cross join generate_series(1, 7, 1) d;
I am trying to write a query in PostgreSQL that should return "month" wise results when two dates are given.
SELECT count(overall_sl) as total_sales, count(CASE WHEN overall_sl < value_1 THEN 1 END) failed_sales
FROM (
SELECT overall_sl, value_1
FROM salecombined c where c.date_updated between '2018-01-01' and '2018-12-31'
GROUP BY dept_name, date_updated, date, overall_sl, no_addons,
value_1, category_id, subcategory_id, branch_name
) sales;
I expect results to be like this (The above query doesn't do that)
start_dt end_dt total_sales failed_sales
-------- ------ ----------- -------------
2018-01-01 2018-01-31 0 0
2018-02-01 2018-02-28 589 154
2018-03-01 2018-03-31 107 14
2018-04-01 2018-04-30 375 114
-- and so on
I wrote below query but it is taking longer to execute; how can I optimise this?
SELECT date_trunc('month', dd):: date start_dt,
(date_trunc('month', dd::DATE) + interval '1 month' - interval '1 day')::date as end_dt,
(select count(overall_sl) from (
SELECT overall_sl
FROM salecombined c
WHERE c.date_updated between date_trunc('month', dd):: date and (date_trunc('month', dd::DATE) + interval '1 month' - interval '1 day')::date
GROUP BY dept_name, date_updated, date, overall_sl, no_addons,
category_id, subcategory_id, branch_name
) jobs
) total_sales,
(select count(CASE WHEN overall_sl < value_1 THEN 1 END) from (
SELECT overall_sl, value_1
FROM salecombined c
WHERE c.date_updated between date_trunc('month', dd):: date and (date_trunc('month', dd::DATE) + interval '1 month' - interval '1 day')::date
GROUP BY dept_name, date_updated, date, overall_sl, no_addons,
value_1, category_id, subcategory_id, branch_name
) jobs
) failed_sales
FROM generate_series
( '2018-01-01'::timestamp
, '2018-12-11'::timestamp
, '1 month'::interval) dd
I am not expert in SQL or PostgreSQL.
I am not quiet sure but maybe you are searching for GROUP BY date_trunc():
demo:db<>fiddle
SELECT
date_trunc('month', sdate)::date as month_begin,
(date_trunc('month', sdate) + interval '1 month -1 day')::date as month_end,
SUM(value)
FROM sales
WHERE sdate BETWEEN <start> and <end>
GROUP BY date_trunc('month', sdate)
date_trunc('month', date) converts the date to the first of the month. So you can group all dates within one month (because all dates are the first of a month in that group)
date_trunc('month', sdate) + interval '1 month -1 day' calculates the last day of a month (date_trunc to go to first, add one month to go the first of the next month, subtract one day to get to the day before the next first = last day of current month.)
I have a table with timestamp field and usage field like this
timestamp | usage
'2015-06-13 13:45:58' | 240
'2015-06-13 13:45:59' | 480
'2015-06-13 13:46:00' | 240
'2015-06-13 13:46:01' | 320
...
I want to get sum of usage for a period of '1 week' with '30 minutes' interval.
I can get data only for intervals in minute, hour, day and ...
SELECT date_trunc('minute', timestamp) as clock, sum(usage)
FROM my_table
WHERE timestamp > localtimestamp - INTERVAL '1 week'
GROUP BY clock
how to get data for intervals like '5 minutes', '30 minutes', '2 days' and ... .
Use the following to get what your after.
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round((extract('epoch' FROM timestamp) / 1800) * 1800) AS clock, SUM(usage)
FROM my_table
WHERE timestamp > localtimestamp - INTERVAL '1 week'
GROUP BY round(extract('epoch' FROM timestamp) / 1800)