I am looking for some guidance on finding number of occurrences of lets say Monday and Wednesday between two dates Date1 and Date2 inclusive of the two dates in Snowflake. Any Suggestions?
A standard practice is to build a calendar table: either as pernament table or inlined view.
CREATE TABLE calendar
AS
SELECT DATEADD(day, ROW_NUMBER() OVER(ORDER BY seq8()), '1999-12-31'::DATE) AS d,
DAYOFWEEK(d) AS day_of_week,
DAYNAME(d) AS day_name
-- month/quarter/year/...
FROM TABLE(GENERATOR(ROWCOUNT => 365*100));
Then:
SELECT c.day_name, COUNT(*) AS cnt
FROM calendar c
WHERE c.d BETWEEN '<date_1>' AND '<date_2>'
AND c.day_of_week IN (1,3)
GROUP BY c.day_name;
Notes: day of week depeneds on parameter WEEK_START.
Lukasz's table solution is quite neat, but I will try the JS version:
// not sure the best name to have here
create or replace function num_of_days_in_between(
day_nums varchar(255),
start_date varchar(10),
end_date varchar(10)
)
RETURNS string
LANGUAGE JAVASCRIPT
AS $$
// perform some validations first on parameters
var s = new Date(START_DATE);
var e = new Date(END_DATE);
var split = DAY_NUMS.split(",");
var count = 0;
var d = s;
// go through each day and check if the
// current day is in the days asked
while (d.getTime() <= e.getTime()) {
// split array contains strings, so we need to
// force getDay() value to be string as well,
// otherwise includes() will not find it
if(split.includes(d.getDay()+"")) {
count++;
}
// advance to the next day
d = new Date(d.getTime() + 86400000);
}
return count;
$$;
-- Monday and Wednesday
select num_of_days_in_between('1,3', '2021-10-01', '2021-11-01'); -- 9
-- Tuesday
select num_of_days_in_between('2', '2021-10-01', '2021-11-01'); -- 4
Note that in JS, days start from Sunday with index of 0, refer to Date.getDay().
Related
I want to get the beginning date of each one third part of year, when I give a date the return must be the first day (date) of this one-third part.
Example: if the parameter is '1-april-2023' the return must be '1-jan-2023'
if the parameter is '1-june-2023' the return must be '1-may-2023'
and so on
We can do some date math by adding 4 months times the (month-1)/4 to the beginning of the year.
CREATE FUNCTION dbo.GetThirdOfYear(#d date)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
(
SELECT Third = DATEADD(MONTH,
4*((MONTH(#d)-1)/4),
DATEFROMPARTS(YEAR(#d),1,1))
);
Sample usage, given a table called Events with a column called EventDate:
SELECT e.EventDate, f.Third
FROM dbo.Events AS e
CROSS APPLY dbo.GetThirdOfYear(e.EventDate) AS f;
Example db<>fiddle (and how I got there).
I have a table containing 3 columns [MONTHNAME], [MONTHSTART] and [MONTHEND]. For reporting, I need to group all prior months together but leave the current month grouped by weeks. To do this I need to get the prior month's ending date. Below is the query I am using and it works properly, but is there a better way of determining the prior month's ending date without creating a table or using CTE with the LAG function? There was no way I found to get the LAG function to return a single value so I had to use the following. Our month ending dates do not fall on the calendar month ending date so I am pulling the data from a custom calendar.
DECLARE #tblMonthEndingDates TABLE
([MONTHSTART] DATE
,[MONTHEND] DATE
)
INSERT INTO #tblMonthEndingDates
VALUES('01-01-2018', '01-26-2018'),
('01-27-2018', '03-02-2018'),
('03-03-2018', '03-30-2018'),
('03-31-2018', '04-27-2018'),
('04-28-2018', '06-01-2018'),
('06-02-2018', '06-30-2018'),
('07-01-2018', '07-27-2018'),
('07-28-2018', '08-31-2018'),
('09-01-2018', '09-28-2018'),
('09-29-2018', '10-26-2018'),
('10-27-2018', '11-30-2018'),
('12-01-2018', '12-31-2018')
DECLARE #dtTbl TABLE(RN INT
,MS DATE
,ME DATE
);
INSERT INTO #dtTbl
SELECT ROW_NUMBER() OVER(ORDER BY [MONTHSTART]) AS ROWNUM
,[MONTHSTART]
,[MONTHEND]
FROM #tblMonthEndingDates;
WITH cteDt
AS
(
SELECT d2.[MS]
,LAG(d1.[ME]) OVER(ORDER BY d1.[MS]) AS PRIORDT
,d2.[ME]
FROM #dtTbl d1
LEFT JOIN #dtTbl d2 ON d1.[RN] = d2.[RN]
)
SELECT [PRIORDT]
FROM cteDt
WHERE [MS] <= GETDATE() AND [ME] >= GETDATE()
So for this month I would want 09-28-2018 as the return value which the query does, I just want to know if there is a better/shorter way of returning that value.
You can do something like this:
Select
Max(MonthEnd)
From #tblMonthEndingDates
Where MonthEnd <= GetDate()
That will give you the most recent MonthEnd date before or on today's date. Obviously, if you need strictly before, you'd use < rather than <=
I used this query to get the start and end dates for the last #n months. You can adapt to meet your needs.
declare #t table (SD date,ED date)
declare #i int = 0
,#SD date
,#ED date
,#datetoEval date
,#EOM date
,#n int = 60
while(#i<=#n)
BEGIN
set #datetoEval = DATEADD(month,-1*#i,getdate())
set #SD = cast(cast(month(#datetoEval) as varchar(2)) + '/1/' + cast(year(#datetoEval) as varchar(4)) as DATE)
set #ED = dateadd(day,-1,DATEADD(MONTH,1,#SD))
insert into #t
values(#SD,#ED)
set #i=#i+1
END
select * from #t
I was overthinking it. Last month ended the day before this one started.
SELECT DATEADD(DAY, -1, MONTHSTART) AS MONTHEND
FROM #tblMonthEndingDates
WHERE
GETDATE() BETWEEN MONTHSTART AND MONTHEND
I am using SQL Server 2008. I'm looking to bring back only the last 7 calendar days of each month, how would I go about doing this.
Thanks
assuming field called logtime, get the range with
....where logtime BETWEEN dateadd(month,month(logtime),dateadd(year, year(logtime) - 1900,0)) - 7
AND
dateadd(month,month(logtime),dateadd(year, year(logtime) - 1900,0)) - 1;
you also need to check that 'logtime' (replaced by your field name) is in the range of dates you are also selecting from e.g ...AND(YEAR(logtime)) = 2016 ..for example
Try this
SELECT
*
FROM
Payments P
WHERE
P.PaymentDay < (SELECT DATEADD(month, ((YEAR(P.PaymentDay) - 1900) * 12) + MONTH(P.PaymentDay), -1)) AND -- Last day of current year-month
P.PaymentDay > (SELECT DATEADD(month, ((YEAR(P.PaymentDay) - 1900) * 12) + MONTH(P.PaymentDay), -7)) -- Last 7. day of current year-month
Some specific examples and direction would help. If you just want rows where, say columnA contains a date that falls within the last 7 days of it's respective month, then you can simply say:
WHERE month(columnA) != month(dateadd(day,7,columnA))
I.e. it asks the question, "given a date, A, does the date 7 days later fall in a different month?"
Note that neither this query nor those include in other answers is able to make use of indexes on this column (since we're using it as an input to a calculation), which is a shame.
Try this:
--DAY(DATE) as day_of_month from day_master table.
select
a.day_id,a.day_of_month
from day_master a LEFT JOIN (select max(day_of_month) as 'max_day_of_month',day_id,month_no,year_no from day_master group by month_no,year_no)b ON b.month_no=a.month_no and a.year_no=b.year_no
where (b.max_day_of_month-a.day_of_month)<7 and a.month_no=11 and a.year_no=2017
GROUP BY a.month_no,a.year_no,a.day_id;
I have an audit table that stores a master table's "status" values in multiple rows, each row has a date/time stamp. Let's call the master table "Project" and it moves through different status changes: Open, Pending, Closed. However sometimes the Project can move back to Open after it's been closed. Data would be something like this:
ProjectId Date Status
1234 07-01-2015 Open
1234 07-03-2015 Pending
1234 07-05-2015 Closed
1234 07-06-2015 Open
I need to take a date parameter value, and determine what status the Project "1234" was in on that given date.
ex: Date=07-02-2015 would give me "Open"
Date=07-07-2015 would also give me "Open"
Date=07-03-2015 would give me "Pending"
The problem I'm having is that the SQL needs to look at the surrounding rows (if any)
1) Limit the rows to only rows with date inside the window.
2) Sort the result by date descending (putting the most recent at the top)
3) Select the first row
DECLARE #CheckDate DATETIME = '07-07-2015',
#ProjectId INT = 1234
-- To ignore time, set the check date to the first millisecond of the
-- next day and use a less than operator
SET #CheckDate = DATEADD(dd, DATEDIFF(dd, 0, #CheckDate) + 1, 0)
SELECT TOP 1
[Status]
FROM [Project]
WHERE [ProjectId] = #ProjectId
AND [Date] < #CheckDate
ORDER BY [Date] DESC
If you have 2012 or later, you can do this with Lead as follows:
declare #date datetime = '7-2-15' --or whatever
select ProjectID, Status from (
select *
, lead(date) over (partition by projectID order by date) as NextEvent
from MyTable) a
where #date between [date] and isnull(NextEvent, #date + 1)
Otherwise, you can approximate lead using row_number and a self-join.
Note, depending on how precise your dates are, you may want to use something like where #date >= date and #date < isnull(NextEvent, #date + 1) instead of between.
I have this model:
class Entry(db.Model):
title = db.StringProperty()
url = db.URLProperty()
date = db.DateTimeProperty(auto_now=True)
image = db.URLProperty()
weight = db.IntegerProperty()
category = db.StringProperty()
desc = db.TextProperty()
I have lots of entries each day, how do I SELECT only today's entries by using GGL ?
since query like this does not return any results ( but I know that there is results ):
SELECT * FROM Entry WHERE category = 'news' and date = '2012-03-12' ORDER BY weight DESC
It's not saved as a string, but as a datetime like object.
The right-hand side of a comparison can be one of the following:
a datetime, date, or time literal, with either numeric values or a
string representation, in the following forms:
DATETIME(year, month, day, hour, minute, second)
DATETIME('YYYY-MM-DD HH:MM:SS')
DATE(year, month, day)
DATE('YYYY-MM-DD')
TIME(hour, minute, second)
TIME('HH:MM:SS')
http://code.google.com/appengine/docs/python/datastore/gqlreference.html
So in your example, use either of these.
date = DATE('2012-03-12')
date = DATE(2012,03,12)
For datetime the time is by default set to 00:00, so equality comparison will fail therefore you must use > to compare
SELECT * FROM Entry WHERE date > DATETIME(yyyy,mm,dd)
If anyone need to looking for a datetime, it works for me in GQL:
select * from tableName where recordDate >= DATETIME('2018-10-07T00:56:36z')
I hope it help to anyone