Get Mondays of the last two months from SQL Server 2008 - sql-server-2008

If today is 10 JULY 2015 then what I need is a record set in SQL Server which has the following records
6 JULY 2015
29 JUNE 2015
22 JUNE 2015
15 JUNE 2015
8 JUNE 2015
1 JUNE 2015
25 MAY 2015

With the following expression you get the last Monday:
CAST(GETDATE()-(##DATEFIRST-1+DATEPART(weekday,GETDATE())) % 7+1 AS DATE)
Here we use ##DATEFIRST and DATEPART(weekday,...) to find the last MONDAY.
Then you should generate 8 (two months) rows sequence of days each of them -7 days prior the next. Here I've used CTE but you can use UNION or TOP 8 rows from existing (system or user) in your DB table to generate 8 rows.
;WITH CT(n) AS
(
SELECT 0
UNION ALL
SELECT n+1 FROM CT WHERE n < 7
)
SELECT DATEADD(DAY,-n*7,
CAST(GETDATE()-
(##DATEFIRST-1+DATEPART(weekday,GETDATE())) % 7+1 AS DATE)) as DT
FROM CT ORDER BY n
Sqlfiddle demo

Try this
;WITH dates AS
(
SELECT CONVERT(datetime,cast(month(getdate())-2 as varchar(2))+'/'+cast(day(getdate()) as varchar(2))+'/'+ cast(year(getdate()) as varchar(4))) as Date,' ' as eid
UNION ALL
SELECT DATEADD(d,1,[Date]),' ' as eid
FROM dates
WHERE DATE < GETDATE()
)
select datename(DD,dates.date)+' '+datename(MM,dates.date)+' '+ datename(YYYY,dates.date) from dates
where datename(dw,dates.date) = 'Monday'

Related

MySQL Select data from table with dates between in reverse of interval 7 days

I have a MySQL requirement to select data from a table based on a start date and end date and group it by weekly also selecting the data in reverse order by date. Assume that, I have chosen the start date as 1st November and the end date as 04 December. Now, I would like to fetch the data as 04 December to 28 November, 27 November to 20 November, 19 November to 12 November and so on and sum the value count for that week.
Given an example table,
id
value
created_at
1
10
2021-10-11
2
13
2021-10-17
3
11
2021-10-25
4
8
2021-11-01
5
1
2021-11-10
6
4
2021-11-18
7
34
2021-11-25
8
17
2021-12-04
Now the result should be like 2021-12-04 to 2021-11-28 as one week, following the same in reverse order and summing the column value data for that week. I have tried in the query to add the interval of 7 days after the end date but it didn't work.
SELECT count(value) AS total, MIN(R.created_at)
FROM data_table AS D
WHERE D.created_at BETWEEN '2021-11-01' AND '2021-12-04' - INTERVAL 7 DAY ORDER BY D.created_at;
And it's also possible to have the last week may have lesser than 7 days.
Expected output:
end_interval
start_interval
total
2021-12-04
2021-11-27
17
2021-11-27
2021-11-20
34
2021-11-20
2021-11-13
4
2021-11-13
2021-11-06
1
2021-11-06
2021-10-30
8
2021-10-30
2021-10-25
11
Note that the last week is only 5 days depending upon the selected from and end dates.
One option to address this problem is to
generate a calendar of all your intervals, beginning from last date till first date, with a split of your choice, using a recursive query
joining back the calendar with the original table
capping start_interval at your start_date value
aggregating values for each interval
You can have three variables to be set, to customize your date intervals and position:
SET #start_date = DATE('2021-10-25');
SET #end_date = DATE('2021-12-04');
SET #interval_days = 7;
Then use the following query, as already described:
WITH RECURSIVE cte AS (
SELECT #end_date AS end_interval,
DATE_SUB(#end_date, INTERVAL #interval_days DAY) AS start_interval
UNION ALL
SELECT start_interval AS end_interval,
GREATEST(DATE(#start_date), DATE_SUB(start_interval, INTERVAL #interval_days DAY)) AS start_interval
FROM cte
WHERE start_interval > #start_date
)
SELECT end_interval, start_interval, SUM(_value) AS total
FROM cte
LEFT JOIN tab
ON tab.created_at BETWEEN start_interval AND end_interval
GROUP BY end_interval, start_interval
Check the demo here.

SQL 4 week period in year grouping

I have an SQL table that contains order data by date. I'm trying to combine the data across years in 4 weeks buckets so that I can compare year on year periods. Luckily the table contains year and week number columns so that I can sum the data to show order totals by week number, for example:
By using SELECT order_year, order_week_number, sum(order_total) from f2l4d1a2ta_237_floodlight_order_data_v1 group by order_week_number ORDER BY order_week_number, order_year
I get:
order_year order_week_number sum(order_total)
2017 1 96.40879041
2017 2 33.34092216
2017 3 97.79772267
2017 4 28.05668819
2017 5 75.79034382
2017 6 41.59171513
2017 7 3.754344347
2017 8 66.27940579
2016 1 65.81290635
2016 2 71.17703765
2016 3 65.95184929
2016 4 90.42108213
2016 5 44.32837015
2016 6 19.9644766
2016 7 53.46359297
2016 8 7.059479081
However what I'm really after is to see the order total for the 4 week period in the year, i.e.
order_year 4 week period sum(order_total)
2017 1 255.6041234
2017 2 187.4158091
2016 1 293.3628754
2016 2 124.8159188
Does anyone know how to group data with SQL in this way?
Thanks,
Matt
Add 3 to the week number then integer divide by 4 (whole number result)
Eg (1+3) DIV 4 = 1, (4+3) DIV 4 = 1
So GROUP BY (weekno + 3) DIV 4

Employee Year Calculation

I have employees table with date_of_join field
and I have employee_leaves table with the following fields:
employee_id
leave_from
leave_to
total_days
the employee joined on 15 Feb 2011
I want to have a query showing the cound of leaves for every employee years based on his date_of_join
for example, if the employee joined on 15 Feb 2011 then the result will be like this:
Feb 2011 to feb 2012 ---- totals days: 21
Feb 2012 to feb 2013 ---- totals days: 26
Feb 2013 to feb 2014 ---- totals days: 8
where Feb to feb is the employee year so it's from 15 Feb to 14 Feb every year
can anyone help please?
Not having your data it is difficult to test this but I came up with the following based on your description:
SELECT employees.employee_id, DATE_ADD(employees.date_of_join, INTERVAL yrs.years) frm
,DATE_ADD(employees.date_of_join, INTERVAL yrs.years + 1) too,
SUM(employee_leaves.total_days)
FROM employee_leaves
INNER JOIN (SELECT 0 years UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) yrs
ON 1=1
INNER JOIN employees ON employee_leaves.employee_id = employees.employee_id
AND employee_leaves.leave_from BETWEEN DATE_ADD(employees.date_of_join, INTERVAL yrs.years) AND DATE_ADD(employees.date_of_join, INTERVAL yrs.years + 1)
GROUP BY employees.employee_id, DATE_ADD(employees.date_of_join, INTERVAL yrs.years)
;
Probably needs some fiddling, hope this helps.

Table Date column comparison with a generated dates list - MYSQL

There seem to be a weird behaviour when comparing a date in table column with a date generated in a list within MYSQL.
Please take a look at the * SQLFIDDLE reference.
Payroll Table:
ID DATESTAMP
1 August, 30 2012 00:00:00+0000
2 September, 02 2012 00:00:00+0000
3 September, 15 2012 00:00:00+0000
4 September, 24 2012 00:00:00+0000
5 October, 05 2012 00:00:00+0000
6 October, 16 2012 00:00:00+0000
7 October, 19 2012 00:00:00+0000
8 November, 02 2012 00:00:00+0000
9 November, 10 2012 00:00:00+0000
10 November, 16 2012 00:00:00+0000
11 November, 24 2012 00:00:00+0000
12 November, 30 2012 00:00:00+0000
13 December, 01 2012 00:00:00+0000
14 December, 07 2012 00:00:00+0000
Dates list is generated between two particular dates with a constant day interval
Query:
set #i:= 0;
SELECT date_format(DATE(ADDDATE('2012-10-05',
INTERVAL #i:=#i+14 DAY)),'%Y-%m-%d')
AS dateP, #i
FROM payroll
HAVING #i < datediff(now(), date '2012-10-05')
;
DATEP #IntervalDays
2012-10-19 14
2012-11-02 28
2012-11-16 42
2012-11-30 56
2012-12-14 70
As you can see the generated dates list has matches to the Payroll table above. However when the comparison is done, it reutns zero records.
Comparison Query:
set #i:= 0;
SELECT distinct datestamp FROM payroll
WHERE date(datestamp) in (
SELECT DATE(ADDDATE('2012-10-05',
INTERVAL #i:=#i+14 DAY) ) AS dateP
FROM payroll
where #i < DATEDIFF(now(), date '2012-10-05')
)
;
So Questions I have:
Is the inner query stop generating dates when used as a nested query?
Is there anything wrong with the dates comparison method I am using here?
What could be the reason for this entire failure?
How to fix it within Select itself without any procedure/functions? :)
PS:
I am also trying to test this in SQL server as well as Oracle.
There are many good questions and answers to support 'Date Comparison' issues occurred at various scenarios with the site. That includes posts such as mysql date comparison with date_format. etc.. May be there's one hidden somewhere asking for exact issue I am facing with different wording. Couldn't find and hence posted the question.
Second UPDATE:
Now I got it working in every version:
select
*
from
Payroll
inner join
(
SELECT DATE(DATE_ADD('2012-10-05',
INTERVAL #i:=#i+14 DAY) ) AS dateP
FROM Payroll, (SELECT #i:=0) r
where #i < DATEDIFF(now(), date '2012-10-05')
) sq on Payroll.datestamp = sq.dateP
You just have to initialize the variable inside the query.
UPDATE:
Strange thing is, this one works on my local machine without problems (version 5.1.41-3ubuntu12.7-log), but not in your SQLfiddle.
set #i:= 0;
select
*
from
Payroll
inner join
(
SELECT DATE(DATE_ADD('2012-10-05',
INTERVAL #i:=#i+14 DAY) ) AS dateP
FROM Payroll
where #i < DATEDIFF(now(), date '2012-10-05')
) sq on Payroll.datestamp = sq.dateP
END OF UPDATE
Have you tried it like this?
set #i:= 0;
SELECT distinct datestamp FROM payroll
WHERE STR_TO_DATE(datestamp, '%M, %d %Y %H:%i:%f') in (
SELECT DATE(ADDDATE('2012-10-05',
INTERVAL #i:=#i+14 DAY) ) AS dateP
FROM payroll
where #i < DATEDIFF(now(), date '2012-10-05')
)
;
My guess is, that the DATE() function fails, cause you're varchar(is it?) date is not in ISO format. Therefore you have to use STR_TO_DATE() function.
For exact usage of STR_TO_DATE() read here and here. I'm not sure about the microsecond part.

Removing the rows from the select after processing

I have to a table like this
Year Month
2012 8
2012 7
2012 4
2012 3
2011 7
2011 3
2011 1
2010 10
2010 9
2010 8
This tables show which month and year is remaning, now let say I have completed 2012, 7 month. Now I want to have list like
Year Month
2012 8
2012 4
2012 3
2011 7
2011 3
2011 1
2010 10
2010 9
2010 8
I am using below query but this is not giving me the correct records
SELECT YEAR, MONTH from tablex
WHERE Year NOT IN (SELECT DISTINCT YEAR from OTHER_TABLE INNER JOIN Some_Other_Table)
AND MONTH NOT IN (SELECT DISTINCT MONTH FROM OTHER_TABLE INNER JOIN Some_Other_Table)
When OTHER_TABLE is null then I am getting the currect count, but when Other table has year 2012 and month 7 I am getting no results.
P.S.: There is no joining columns available for tablex and OTHER_TABLE and Som_Other_Table
You just have to use NOT EXISTS:
SELECT YEAR, MONTH
from tablex t1
WHERE NOT EXISTS
(
SELECT 1 FROM OTHER_TABLE t2
WHERE t2.Year = t1.Year AND t2.Month = t2.Month
)
This answer assumes you have a single row {Year = 2012, Month = 7} in OTHER_TABLE to designate the completed month.
This won't work because you're checking the year and month separately. Therefore you are not removing the row (2012, 7) from the results, you're removing all rows with Year = 2012 and all rows with Month = 7. Try this anti-join instead:
SELECT x.YEAR, x.MONTH
FROM tablex x
LEFT OUTER JOIN OTHER_TABLE y ON x.YEAR = y.YEAR AND x.MONTH = y.MONTH
WHERE y.YEAR IS NULL