I have an embedded query that I use to pull previous month data. Everything has been working fine until this month (January). My code looks like this:
(MONTH(CURRENT DATE)-1) = MONTH(TSTAMP)
I have it setup this way because I have a timestamp in my data that I base the query off of. This usually works like a charm, but it's not working this month and I think it's because of the new year. How does this function work when dealing with a different year? Is there a way to write it into the query so I don't have to worry about a change in year?
You can do this by using the year, like this:
YEAR(CURRENT DATE) * 12 + MONTH(CURRENT DATE) - 1 = YEAR(TSTAMP) * 12 + MONTH(TSTAMP)
This, in essence, converts the dates into months since time 0 -- so the -1 makes sense.
The proper way to do this is with a range query (one with an exclusive upper-bound, <, too), so that the db is free to us an index if one is available.
The first of the month can be retrieved pretty easily via:
CURRENT_DATE - (DAY(CURRENT_DATE) - 1) DAYS
(Subtract the difference in days between the current date and the start of the month)
This gives a wonderful upper-bound condition for the query:
WHERE tStamp < CURRENT_DATE - (DAY(CURRENT_DATE) - 1) DAYS
(Get everything before the start of the current month).
However, since we're really only interested in the previous month, we also need to limit the lower bound. Well that's everything since, or on, the start of that month... and since we can already get the start of the current month:
WHERE tStamp >= CURRENT_DATE - (DAY(CURRENT_DATE) - 1) DAYS + 1 MONTH
AND tStamp < CURRENT_DATE - (DAY(CURRENT_DATE) - 1) DAYS
There's a related way to do this, supposing you have a calendar table with appropriate indices. If you have a minimal table with these columns:
calendarDate - DATE
year - INTEGER
month - INTEGER
dayOfMonth - INTEGER
... you can use this table to get the relevant values instead:
WHERE tStamp >= (SELECT calendarDate
FROM calendarTable
WHERE year = YEAR(CURRENT_DATE - 1 MONTH)
AND month = MONTH(CURRENT_DATE - 1 MONTH)
AND dayOfMonth = 1)
AND tStamp < (SELECT calendarDate
FROM calendarTable
WHERE year = YEAR(CURRENT_DATE)
AND month = MONTH(CURRENT_DATE)
AND dayOfMonth = 1)
(there's a couple of different forms of this, but this one looks pretty simple)
Related
I have a below query that I run to extract material movements from the last 7 days.
Purpose is to get the data for the last calender week for certain reports.
select
*
From
redshift
where
posting_date between CURRENT_DATE - 7 and CURRENT_DATE - 1
That means I need to run the query on every Monday to get the data for the former week.
Sometimes I am too busy on Monday or its vacation/bank holiday. In that case I would need to change the query or pull the data via SAP.
Question:
Is there a function for redshift that pulls out the data for the last calender week regardless when I run the query?
I already found following solution
SELECT id FROM table1
WHERE YEARWEEK(date) = YEARWEEK(NOW() - INTERVAL 1 WEEK)
But this doesnt seem to be working for redshift sql
Thanks a lot for your help.
Redshift offers a DATE_TRUNC('week', datestamp) function. Given any datestamp value, either a date or datetime, it gives back the date of the preceding Sunday.
So this might work for you. It filters rows from the Sunday before last, up until but not including, the last Sunday, and so gets a full week.
SELECT id
FROM table1
WHERE date >= DATE_TRUNC('week', NOW()) - INTERVAL 1 WEEK
AND date < DATE_TRUNC('week', NOW())
Pro tip: Every minute you spend learning your DBMS's date/time functions will save you an hour in programming.
I am running the below query to get data recorded in the past 24 hours. I need the same data recorded starting midnight (DATE > 12:00 AM) and also data recorded starting beginning of the month. Not sure if using between will work or if there is better option. Any suggestions.
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CNLD'
AND
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
Output (Just need Count). OPEN_DATE Data Type is NUMBER. the output below displays count in last 24 hours. I need the count beginning midnight and another count starting beginning of the month.
The query you've shown will get the count of rows where OPEN_DATE is an 'epoch date' number representing time after midnight this morning*. The condition:
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
requires every OPEN_DATE value in your table (or at least all those for CNLD rows) to be converted from a number to an actual date, which is going to be doing a lot more work than necessary, and would stop a standard index against that column being used. It could be rewritten as:
OPEN_DATE >= (trunc(sysdate) - date '1970-01-01') * 86400
which converts midnight this morning to its epoch equivalent, once, and compares all the numbers against that value; using an index if there is one and the optimiser thinks it's appropriate.
To get everything since the start of the month you could just change the default behaviour of trunc(), which is to truncate to the 'DD' element, to truncate to the start of the month instead:
OPEN_DATE >= (trunc(sysdate, 'MM') - date '1970-01-01') * 86400
And the the last 24 hours, subtract a day from the current time instead of truncating it:
OPEN_DATE >= ((sysdate - 1) - date '1970-01-01') * 86400
db<>fiddle with some made-up data to get 72 back for today, more for the last 24 hours, and more still for the whole month.
Based on your current query I'm assuming there won't be any future-dated values, so you don't need to worry about an upper bound for any of these.
*Ignoring leap seconds...
It sounds like you have a column that is of data type TIMESTAMP and you only want to select rows where that TIMESTAMP indicates that it is today's date? And as a related problem, you want to find those that are the current month, based on some system values like CURRENT TIMESTAMP and CURRENT DATE? If so, let's call your column TRANSACTION_TIMESTAMP instead of (reserved word) DATE. Your first query could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
DATE(TRANSACTION_TIMESTAMP)=CURRENT DATE
The second example of finding all for the current month up to today's date could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
YEAR(DATE(TRANSACTION_TIMESTAMP)=YEAR(CURRENT DATE) AND
MONTH(DATE(TRANSACTION_TIMESTAMP)=MONTH(CURRENT DATE) AND
DAY(DATE(TRANSACTION_TIMESTAMP)<=DAY(CURRENT DATE)
I am new to Big Query. I am trying to do a where condition to only select yesterday's data and that of same day last year (in this case, 10/25/2021 data and 10/25/2020 data). I know how to select a range of data, but I couldn't figure out a way to only select those 2 days of data. Any help is appreciated.
I recommend using BigQuery functions to define dates. You can read about them here.
WHERE DATE(your_date_field) IN ((DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY),
DATE_SUB(DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY), INTERVAL 1 YEAR))
This is dynamic to any day that you run the query. It will take the current date, then subtract 1 day. For the other date, it will take the current date and subtract 1 day and then 1 year, making it yesterday's date 1 year prior.
WHERE date_my_field IN (DATE('2021-10-25'), DATE('2020-10-25'))
Use IN which is a short cut for OR operator
Consider below (less verbose approach - especially if you remove time zone)
select
current_date('America/Los_Angeles') - 1 as yesterday,
date(current_date('America/Los_Angeles') - 1 - interval 1 year) same_day_last_year
with output
So, now you can use it in your WHERE clause as in below example (with dummy data via CTE)
with data as (
select your_date_field
from unnest(generate_date_array(current_date() - 1000, current_date())) your_date_field
)
select *
from data
where your_date_field in (
current_date('America/Los_Angeles') - 1,
date(current_date('America/Los_Angeles') - 1 - interval 1 year)
)
with output
I need a query which can generate the total no of records generated in the previous month.
I started with this query:
select state, taxing_entity, count(taxing_entity) Total_TRXN_Count
from taxes where effect_date between '2016/07/01' and '2016/07/31'
group by state, taxing_entity, effect_date
But I need a query which can dynamically calculate the no of records for a previous month without hard coding the dates. I tried many queries like:
SELECT * FROM taxes
WHERE effect_date >= DATEADD(day,-30, getdate())
and effect_date <= getdate()
and
SELECT *
FROM taxes
WHERE effect_date >= DATEADD(effect_date, -1, GETDATE())
but I have had no success until now. Can someone please suggest a way to get the total records from a previous month using the Informix dialect of SQL?
Background
You can do it with Informix functions TODAY, MONTH(), YEAR() and MDY() — and a little jiggery-pokery.
The expression for the first day of this month is:
MDY(MONTH(TODAY), 1, YEAR(TODAY))
The expression for the first day of the prior month, therefore, is:
MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH
The advantage of these expressions is that they are unambiguous and reliable; they don't depend on anything special (in the SQL you write) to find the last day of the month. You can find the last day of the month by subtracting 1 UNITS DAY from the first day of the following month. With modern versions of Informix, you can do date arithmetic that rounds to the end of month:
SELECT MDY(1,31,2016) + 1 UNITS MONTH FROM sysmaster:'informix'.sysdual;
2016-02-29
but older versions of Informix would generate an error instead. Even now, MDY(2,31,2016) generates an 'invalid day in month' error.
Answer
So for the problem in the question, the date range you want is:
SELECT *
FROM taxes
WHERE effect_date >= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
AND effect_date < MDY(MONTH(TODAY), 1, YEAR(TODAY))
It is easier to use 'before the first day of this month' than to use 'on or before the last day of the previous month'. However you could write:
SELECT *
FROM taxes
WHERE effect_date >= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
AND effect_date <= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS DAY)
or, equivalently:
SELECT *
FROM taxes
WHERE effect_date BETWEEN (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
AND (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS DAY)
Using stored procedures
You could generalize the code by using any chosen date in place of TODAY, and you could write one or two simple stored procedures to do those calculations if you think they're too obscure as shown. Possible names would include first_day_this_month and first_day_prev_month, passing the reference date as an argument, defaulting to TODAY:
CREATE PROCEDURE first_day_this_month(refdate DATE DEFAULT TODAY)
RETURNING DATE AS first_day;
RETURN MDY(MONTH(refdate), 1, YEAR(refdate));
END PROCEDURE;
CREATE PROCEDURE first_day_prev_month(refdate DATE DEFAULT TODAY)
RETURNING DATE AS first_day;
RETURN MDY(MONTH(refdate), 1, YEAR(refdate)) - 1 UNITS MONTH;
END PROCEDURE;
Example use (assuming you have DBDATE='Y4MD-' or equivalent in your environment, so DATE strings look like ISO 8601 or DATETIME strings):
SELECT first_day_this_month() AS aug_1,
first_day_prev_month() AS jul_1,
first_day_this_month(DATE('2015-12-25')) as dec_1,
first_day_prev_month(DATE('2015-10-31')) AS sep_1
FROM sysmaster:'informix'.sysdual;
Output:
aug_1 jul_1 dec_1 sep_1
2016-08-01 2016-07-01 2015-12-01 2015-09-01
And hence:
SELECT *
FROM taxes
WHERE effect_date >= first_day_prev_month()
AND effect_date < first_day_this_month()
A few years old but I assume this is still relevant info:
effect_date >=
MDY(month(current - 1 units month), 1, year(current - 1 units month))
and effect_date <
MDY(month(current), 1, year(current))
http://www.dbforums.com/showthread.php?1627297-Informix-query-to-find-first-date-of-previous-month
Of course if you were given a random date and you need to cover it's month from the first to the end, the pattern is similar:
effect_date >=
MDY(month(<given_date>), 1, year(<given_date>))
and effect_date <
MDY(month(<given_date> + 1 units month), 1, year(<given_date> + 1 units month))
well I had this prepared because sql-server was tagged you can translate the it to informix maybe I will look it up too.
SELECT *
FROM
taxes
WHERE
effect_date >= DATEFROMPARTS(YEAR(DATEADD(MONTH,-1,GETDATE())),MONTH(DATEADD(MONTH,-1,GETDATE())),1)
AND effect_date < DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1)
I think infomix might just be:
SELECT *
FROM
taxes
WHERE
effect_date >= MDY(MONTH(ADD_MONTHS(CURRENT,-1)),1,YEAR(ADD_MONTHS(CURRENT,-1)))
AND effect_date < MDY(MONTH(CURRENT),1,YEAR(CURRENT))
If you change from <= to < then you really don't have to search by end of last month but rather than beginning of this month. Which if you effect_date has time included would actually be what you want because of the midnight issue.
This should work in MSSQL:
SELECT COUNT(*)
FROM taxes
WHERE effect_date >= DATEADD(MONTH, -1, effect_date)
I'm not too familiar with Informix, but the syntax shouldn't be too far off.
I am trying to extract dates which are 2 days after the current date, unless in the case that two days after the current date would be a weekend, in which case I am lookig for dates that are 4 days after the current date. I am using Data Studio and none of the sql functions (like dateadd) work on it.
I know I can get the dates I want using this pull:
select event_end_date from mdmins11.contract where event_end_date between (current date +1.9 days) and (current date + 2.1 days);
But this does not exclude the weekends. I was trying to do it mathematically as such:
select event_end_date
case(
when (current date + 2 days) = ('2014-09-06' + (7 days * int)) or ('2014-09-07' + (7 days * int))
then set #w = (current date + 4 days)
else set #w = (current date + 2 days)
)
from mdmins11.contract where event_end_date = #w;
Here I am trying to find the dates that are after Saturdays and Sundays in case (current date + 2) lands on a weekend. This is not working at all. Does anyone have any idea how to do this on sql without using the functions? I appriciate that my date formatting might be wrong but I am finding it hard to see the solution.
I found the answer! For anyone who is in the same situation:
select dayofweek(current date) as day_number,
event_end_date
from mdmins11.contract
where (dayofweek(event_end_date) = 6 /*Friday*/
and date(event_end_date) < current_date + 3 days
and date(event_end_date) >= current_date)
or (dayofweek(event_end_date) in (1,2,3,4,5,7) /*All other days of week*/
and date(event_end_date) < current_date + 2 days
and date(event_end_date) >= current_date)
;
If you happen to have a list of holiday dates, you can also incorporate this in.