How to Convert number to date - sql-server-2008

How should I convert number to date?
for example:-
I would like to enter number as 31, it should find which all months has date as 31 and it should show out put as below for current year.
Date Day
31-01-2013 Thursday
31-03-2013 Sunday
And how should I convert number to date.

I'm not sure if this is exactly what you want to do, but if you create a calendar table first then it's a very simple query:
select [Date], [Day]
from dbo.Calendar
where YearNumber = 2013 and DayNumber = 31

You could use the day() function to compare the day in your date column to the value that you provide. Then you can use datename() to get the weekday:
declare #val int = 31
select dt, datename(dw, dt)
from yourtable
where day(dt) = #val
See SQL Fiddle with Demo

SQL Fiddle
MS SQL Server 2008 Schema Setup:
Query 1:
declare #Day int;
set #Day = 31
select D.D,
datename(weekday, D.D) as DOW
from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) as M(M)
cross apply (select dateadd(day,
#Day - 1,
dateadd(month,
M.M - 1,
dateadd(year,
year(getdate()) - 1,
cast('00010101' as date))))) as D(D)
where day(D.D) = #Day
Results:
| D | DOW |
--------------------------
| 2013-01-31 | Thursday |
| 2013-03-31 | Sunday |
| 2013-05-31 | Friday |
| 2013-07-31 | Wednesday |
| 2013-08-31 | Saturday |
| 2013-10-31 | Thursday |
| 2013-12-31 | Tuesday |

Related

Generate a weekly calendar based upon Week Start and Week End dates

I'm trying to create a script that would give me the fiscal weeks based upon reference dates of Start Week and End Week
For example, assume that I have table columns with StartWeek and EndWeek such that:
StartWeek | EndWeek
----------|---------
20190603 | 20190609
20190610 | 20190616
20190617 | 20190623
20190624 | 20190630
20190701 | 20190707
...
I would like a script to generate the following:
FiscalDateStart | FiscalDateEnd | NumOfDays | WeekDayStart | WeekDayEnd
----------------|----------------|------------|--------------|-----------
2019-06-05 | 2019-06-09 | 5 | Wednesday | Sunday
2019-06-10 | 2019-06-16 | 7 | Monday | Sunday
2019-06-17 | 2019-06-23 | 7 | Monday | Sunday
2019-06-24 | 2019-06-30 | 7 | Monday | Sunday
2019-07-01 | 2019-07-02 | 2 | Monday | Tuesday
I have found the following logic on Stack:
DECLARE #StartDate DATE = '2019-06-05'
, #EndDate DATE = '2019-07-02'
SET DATEFIRST 1
SET LANGUAGE French;
SET NOCOUNT ON;
select *
from
(Select
WeekNum = Dense_Rank() over (Partition By FY,FM Order By FW)
,StartDate = Min(D) over (Partition By FY,FM,FW )
,EndDate = Max(D) over (Partition By FY,FM,FW )
,NumOfDays = DATEDIFF(DAY, Min(D) over (Partition By FY,FM,FW ), Max(D) over (Partition By FY,FM,FW )) + 1
From
(
/* Establish calendar rules/functions for Fiscal Year (FY), Fiscal Month (FM), Fiscal Week (FW), & Fiscal Day (D) */
Select FY = DatePart(Year,#StartDate)-1+sum(case when convert(varchar(5),#StartDate,101)=convert(varchar(5),D,101) then 1 else 0 end) over (Order By D)
,FM = sum(case when DatePart(Day,D)=DatePart(Day,#StartDate) then 1 else 0 end) over (Order By D)
,FW = sum(case when DatePart(WeekDay,D)=1 then 1 else 0 end) over (Order By D)
,D
From (
/* Generate Fiscal Day (D) rule based on #StartDate & #EndDate */
Select Top (DateDiff(DAY,#StartDate,#EndDate)+1)
D = DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),#StartDate)
From master..spt_values n1,master..spt_values n2
) A1
) A
--Order By D
) a
group by
WeekNum, StartDate, EndDate, NumOfDays
The issue is that we're forcing the #StartDate in the above query to be as of 2019-06-05. However, I need the above script to generate the same results, but based upon the #StartDate as of 2019-06-03.
Any help would be appreciated.

SQL sum multiple values by date into new values by date

Hi I have reports that have been issued with some regularity but they have an initial value of accounts for when the report value is null.
I would like to create a new variable Accts_N which occurs for School, Year, and date and is the sum of that date's Accts value and the Accts value when the date is null.
So, using the sample table below, School A Year 2017 would have a Accts_N value of 8 for 2016-01-10 and a value of 12 for 2016-02-10.
School | Year | Accts | ReportDate
-------|------|-------|-----------
A | 2017 | 2 | null
A | 2017 | 6 | 2016-01-10
A | 2017 | 10 | 2016-02-10
A | 2018 | 0 | 2016-01-10
A | 2018 | 4 | 2016-02-10
B | 2017 | 9 | null
B | 2018 | 3 | 2016-2-10
I've tried a few different instances of SUM CASE WHEN but I don't think that's the right approach. Can someone suggest a direction for me?
Thank you
If you want to add a new column, then a correlated subquery comes to mind:
select r.*,
(select sum(r2.accts)
from reports r2
where r2.school = r.school and
r2.year = r.year and
(r2.reportdate = r.reportdate or r2.reportdate is null)
) as accts_n
from reports r;
How about this?
declare #t table(School nvarchar(50), Year datetime, Accts int, ReportDate datetime)
insert into #t
values
('A','2017',2,null),
('A','2017',6,'2016-01-10'),
('A','2017',10,'2016-02-10'),
('A','2018',0,'2016-01-10'),
('A','2018',4,'2016-02-10'),
('B','2017',9,null),
('B','2018',3,'2016-01-10')
select t.School, t.Year, t.ReportDate, t.Accts + ISNULL(tNulls.SumAcctsWhenNull,0)
from #t t
outer apply (select t2.School, t2.Year, SUM(Accts) AS SumAcctsWhenNull
from #t t2
where
t2.ReportDate IS NULL AND
t2.School = t.School AND
t2.Year = t.Year
group by t2.School, t2.Year) tNulls
where
t.ReportDate IS NOT NULL

SQL/Mysql Query available dates in database

I need some help querying my calendar/dates table
Scenario:
I have a "calendar" table with dates, user will set his available dates, usually day by day. So my table looks like this:
+------+------------+---------------------+---------------------+
| ID | user_id | start_date | end_date |
+------+------------+---------------------+---------------------+
| 1 | 1 | 2016-09-01 08:00:00 | 2016-09-01 16:00:00 |
| 2 | 1 | 2016-09-03 08:00:00 | 2016-09-03 16:00:00 |
| 3 | 1 | 2016-09-04 08:00:00 | 2016-09-04 16:00:00 |
| 3 | 1 | 2016-09-05 08:00:00 | 2016-09-05 16:00:00 |
+------+------------+---------------------+---------------------+
This means user 1 is available on the 1st, 3rd, 4th and 5th.
Lets say I want to query the table and find if user is available from date 2016-09-01 08:00:00 to 2016-09-05 16:00:00, this query must return zero rows since the user is not available on the 2nd of September. But if query from date 2016-09-03 08:00:00 to 2016-09-05 16:00: 00 then it will return these 3 rows.
Hope someone can help me with this
This could be one way (for a single user).
Note #endDate and #startDate are the supplied date fields to search.
SELECT
*
FROM your_table
WHERE EXISTS (
SELECT
user_id
FROM your_table
WHERE start_date >= #startDate
AND start_date <= #endDate
AND user_id = 1
GROUP BY user_id
HAVING SUM((DATEDIFF(end_date,start_date)+1)) = DATEDIFF(#endDate,#startDate)+1
)
AND start_date >= #startDate
AND start_date <= #endDate
AND user_id = 1
Note:
If the supplied date range falls within any range bounded by start_date and end_date (exclusive) then it won't work.
Since SUM((DATEDIFF(end_date,start_date)+1)) = DATEDIFF(#endDate,#startDate)+1 won't be equal in this case. Condition
In this case, you need to stay within the required boundary. Here the boundary is demarcated by the smaller value of end_date and #endDate and the larger value of start_date and #startDate.
Suppose, you have the following record (only one)
start_date = 2016-09-01 and end_date=2016-09-05.
And #startDate=2016-09-02 , #endDate=2016-09-04
Now check the above condition will fail for this set of data.
In this case you need to adopt the following query:
SELECT
*
FROM your_table
WHERE EXISTS (
SELECT
user_id
FROM your_table
WHERE end_date >= #startDate
AND start_date <= #endDate
AND user_id = 1
GROUP BY user_id
HAVING SUM((DATEDIFF(LEAST(end_date,#endDate),GREATEST(start_date,#startDate))+1)) = DATEDIFF(#endDate,#startDate)+1
)
AND end_date >= #startDate
AND start_date <= #endDate
AND user_id = 1
Assuming the periods in the table are not overlapping, you can count the number of days. The days in the period are then:
select sum(datediff(least($period_end, end_date),
greatest($period_start, start_date)
) + 1
)
from t
where $period_start <= end_date and
$period_end >= start_date;
You can then get a flag by comparing to the number of days:
select (case when sum(datediff(least($period_end, end_date),
greatest($period_start, start_date)
) + 1
) =
datediff($period_end, $period_start) + 1
then 1 else 0
end) as IsAvailableForAllDays
from t
where $period_start <= end_date and
$period_end >= start_date;

selecting dates till current date - mysql [duplicate]

This question already has answers here:
How to populate a table with a range of dates?
(10 answers)
Closed 8 years ago.
Today is 20th Aug 2013.
I want to generate 20 rows which will contain dates from 1st to 20th (whatever would be the current date) of the month by using mysql query.
Count should always start from 1st date of the month and till current date... output would be like, only one column and multiple rows till current date like given below..
Current month
8/1/13 12:00 AM
8/2/13 12:00 AM
8/3/13 12:00 AM
8/4/13 12:00 AM
8/5/13 12:00 AM
8/6/13 12:00 AM
8/7/13 12:00 AM
8/8/13 12:00 AM
8/9/13 12:00 AM
8/10/13 12:00 AM
8/11/13 12:00 AM
8/12/13 12:00 AM
8/13/13 12:00 AM
8/14/13 12:00 AM
8/15/13 12:00 AM
8/16/13 12:00 AM
8/17/13 12:00 AM
8/18/13 12:00 AM
8/19/13 12:00 AM
8/20/13 12:00 AM
I tried following query but is of no use. Can you please help to find some other workaround for this?
DECLARE #startDate DATETIME=CAST(MONTH(GETDATE()) AS VARCHAR) + '/' + '01/' + + CAST(YEAR(GETDATE()) AS VARCHAR) -- mm/dd/yyyy
DECLARE #endDate DATETIME= GETDATE() -- mm/dd/yyyy
;WITH Calender AS
(
SELECT #startDate AS CalanderDate
UNION ALL
SELECT CalanderDate + 1 FROM Calender
WHERE CalanderDate + 1 <= #endDate
)
SELECT [Date] = CONVERT(VARCHAR(10),CalanderDate,25)
FROM Calender
OPTION (MAXRECURSION 0)
This too would work by dynamically building a result set of all days, but can work against any existing table you have that has as least 31 days (max for any given month).
select
#curDay := date_add( #curDay, interval 1 day ) as CalendarDay
from
( select #curDay := date_add( DATE_FORMAT(NOW(),
'%Y-%m-01'), interval -1 day) ) sqlvars,
AnyTableInYourDatabaseWithAtLeast31Records
where
#curDay <= now()
limit
31
The first part of select #curDay builds whatever the current day is, gets to the first of the month, then subtracts 1 day from it giving you the last day of the previous month. Then, the outer select #curDay := keeps updating itself by adding 1 day as the CalendarDay result column. Since its a join to "any table" in your database, it will keep grabbing a MAX of 31 records, but only return where the date is less than or current to now.
Fiddle at
http://www.sqlfiddle.com/#!2/28466/1
CREATE TABLE CALENDAR(DATE1 DATETIME);
INSERT INTO CALENDAR VALUES ('2013/8/1 12:00:00');
INSERT INTO CALENDAR VALUES ('2013/8/2 12:00:00');
INSERT INTO CALENDAR VALUES ('2013/8/3 12:00:00');
INSERT INTO CALENDAR VALUES ('2013/8/4 12:00:00');....
SELECT DISTINCT DATE1 FROM Calender where MONTH(DATE1)=MONTH(NOW()) and DAYOFMONTH(DATE1) <=DAYOFMONTH(NOW())
This gives the output
I like to use tally tables for these sorts of problems, they tend to be pretty fast:
DECLARE #startDate DATETIME= CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(GETDATE())-1),GETDATE()),101);
WITH
N0 as (SELECT 1 as n UNION ALL SELECT 1)
,N1 as (SELECT 1 as n FROM N0 AS t1 CROSS JOIN N0 AS t2)
,N2 as (SELECT 1 as n FROM N1 AS t1 CROSS JOIN N1 AS t2)
,N3 as (SELECT 1 as n FROM N2 AS t1 CROSS JOIN N2 AS t2)
,N4 as (SELECT 1 as n FROM N3 AS t1 CROSS JOIN N3 AS t2)
,N5 as (SELECT 1 as n FROM N4 AS t1 CROSS JOIN N4 AS t2)
,N6 as (SELECT 1 as n FROM N5 AS t1 CROSS JOIN N5 AS t2)
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
SELECT DATEADD(day,num-1,#startDate) as theDate
FROM nums
WHERE num <= DATEDIFF(day,#startDate,GETDATE()) + 1
You could try calling this Stored Procedure;
DELIMITER $$
CREATE PROCEDURE `test`.`GenerateDates` ()
BEGIN
DECLARE Days INTEGER;
DECLARE Count INTEGER;
SET Days = DATEDIFF(NOW(),CONCAT(YEAR(NOW()),'-',MONTH(NOW()),'-01'));
SET Count = 0;
DROP TEMPORARY TABLE IF EXISTS tempDates;
CREATE TEMPORARY TABLE tempDates
(
YourDate Date,
PRIMARY KEY(YourDate)
);
WHILE (Count <= Days) DO
INSERT INTO tempDates (YourDate) VALUES
(DATE_FORMAT(DATE_ADD(CONCAT(YEAR(NOW()),'-',MONTH(NOW()),'-01'), INTERVAL Count DAY),'%Y-%m-%d'));
SET Count = Count + 1;
END WHILE;
SELECT * FROM tempDates;
END
:) ... or if a table of 31 integers seems like a stretch, how about a table of 10...
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT DATE_FORMAT(CURDATE(),'%Y-%m-01')+INTERVAL i2.i*10+i1.i DAY x FROM ints i1, ints i2 HAVING x <= NOW();
+------------+
| x |
+------------+
| 2013-08-01 |
| 2013-08-02 |
| 2013-08-03 |
| 2013-08-04 |
| 2013-08-05 |
| 2013-08-06 |
| 2013-08-07 |
| 2013-08-08 |
| 2013-08-09 |
| 2013-08-10 |
| 2013-08-11 |
| 2013-08-12 |
| 2013-08-13 |
| 2013-08-14 |
| 2013-08-15 |
| 2013-08-16 |
| 2013-08-17 |
| 2013-08-18 |
| 2013-08-19 |
| 2013-08-20 |
+------------+
(still not sure why you'd do this in MySQL)

issue with loops in sql server 2008

I am facing issues with my query:
select week_number
,year
from accounting_calender
where week_number<=3
and week_number>3-6
and year=2013
Here in this query I'm passing the week_number 3 and year 2013 through my reporting tool.
I'm getting the following output:
| Week_number | year |
----------------------
| 3 | 2013 |
| 2 | 2013 |
| 1 | 2013 |
But here in my accounting calender table I returned entries for 2012 too.
So here I'm subtracting -6, so it has to go to previous year weeks also.
I am looking for something like below output:
| Week_number | year |
----------------------
| 51 | 2012 |
| 52 | 2012 |
| 53 | 2012 |
| 3 | 2013 |
| 2 | 2013 |
| 1 | 2013 |
I have read-only access.
You'll need to add a special case where the previous 6 weeks cross a year boundary:
select
week_number,
year
from
accounting_calender
where
(week_number > #week-6 and week_number <= #week and year=#year)
or
(week_number > #week-6+53 and year=#year-1)
If #week >= 6, then the second condition will always be > 53 so it will have no effect. However, if #week < 6, then the second condition will be 52, 51, etc. for the previous year.
Converting your weeks and years into dates will make it much easier to perform additions to your date range:
DECLARE #Week_Number INT
DECLARE #Year INT
DECLARE #WeeksToGet INT
SET #Week_Number = 3
SET #Year = 2013
SET #WeeksToGet = 6
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #EndDate = DATEADD(WEEK, #Week_Number, DATEADD(YEAR, #Year - 1900, 0))
SET #StartDate= DATEADD(WEEK, -6, #EndDate)
select
week_number,
year
from accounting_calender
where
DATEADD(WEEK, week_number, DATEADD(YEAR, year - 1900, 0)) between
#StartDate AND #EndDate
However, note that this will obfuscate any indexes that you have on week_number and year. If this is a concern, you might consider changing these columns into a DATE type so that you can avoid having to convert the two columns into one date.
Sql Fiddle