converting varchar(50) to datetime and populating rest of the table - sql

I am working on a data warehouse and in the data model theres a dimension table dim.date which needs to be populated from excel sheet.
this is table structure
CREATE TABLE timeme
(
datekey INT IDENTITY NOT NULL,
fulldate VARCHAR(50),
englishdayname VARCHAR(20),
englishmonthname VARCHAR(20),
daynumberofthemonth INT,
daynumbarofyear INT,
weeknumberofyear INT,
calenderquater INT,
calenderyear INT
)
INSERT INTO timeme
(fulldate)
VALUES ('03-13-2013-02:41:38'),
('03-13-2013-02:39:50'),
('03-13-2013-02:53:15'),
('03-13-2013-02:59:47')
This is what i tried
-- select * from timeme
--update timeme set fulldate= cast(left(fulldate, 10)+ ' ' +replace(substring(fulldate, 12, 12), '.', ':') as datetime)-- but it should be 2013-03-13 02:41:38.000
UPDATE timeme
SET englishdayname = Datename(dw, fulldate),
englishmonthname = Datename(mm, fulldate),
daynumberofthemonth = Datepart(d, fulldate)
Update timeme
SET daynumbarofyear -- this i didnt get rest how to populate
can somebody help me populating entire table

Are you looking for this?
UPDATE timeme
SET fulldate = SUBSTRING(fulldate, 7, 4) + '-' + LEFT(fulldate, 5) + ' ' + RIGHT(fulldate, 8);
UPDATE timeme
SET englishdayname = DATENAME(dw, CAST(fulldate AS DATE)),
englishmonthname = DATENAME(mm, CAST(fulldate AS DATE)),
daynumberofthemonth = DATEPART(dd, CAST(fulldate AS DATE)),
daynumbarofyear = DATEPART(dy, CAST(fulldate AS DATE)),
weeknumberofyear = DATEPART(ww, CAST(fulldate AS DATE)), -- or isoww instead of ww
calenderquater = DATEPART(qq, CAST(fulldate AS DATE)),
calenderyear = DATEPART(yy, CAST(fulldate AS DATE));
Outcome:
| DATEKEY | FULLDATE | ENGLISHDAYNAME | ENGLISHMONTHNAME | DAYNUMBEROFTHEMONTH | DAYNUMBAROFYEAR | WEEKNUMBEROFYEAR | CALENDERQUATER | CALENDERYEAR |
|---------|---------------------|----------------|------------------|---------------------|-----------------|------------------|----------------|--------------|
| 1 | 2013-03-13 02:41:38 | Wednesday | March | 13 | 72 | 11 | 1 | 2013 |
| 2 | 2013-03-13 02:39:50 | Wednesday | March | 13 | 72 | 11 | 1 | 2013 |
| 3 | 2013-03-13 02:53:15 | Wednesday | March | 13 | 72 | 11 | 1 | 2013 |
| 4 | 2013-03-13 02:59:47 | Wednesday | March | 13 | 72 | 11 | 1 | 2013 |
Here is SQLFiddle demo

Related

Populate a row in SQL Server based on a condition (query optimization)

I am trying to find all the people who took a timeoff for previous months, I got most of it. But if nobody took a timeoff in the current month, I need to populate a row saying 0 to get my visuals right.
This is what my data looks like:
This is what I have for the visual:
select s.*, DATEPART(MONTH, startd) as timeoff_Mon,
DATEDIFF(day, startd, endd) as timeoff, getdate() as dat,
DATEPART(MONTH, GETDATE()) as Current_Mon from sample s;
You can see that Jack was the only employee who took time off in January for a day, and John in Feb for 4 days,
Now, in March, I have got the current month which is the last column in the image above from the current date.
Using this current month, is there a way to populate a row or hardcode a row to populate the time off column as 0??
Desired Output:
Here is the SQL Fiddle with the above-mentioned problem.
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=9e8fbb2ae8dcfec9cc5fdfa784782753
A simple option is to use union all to add the final record if there is no row that overlaps the current month in the table:
select
s.*,
month(startd) as timeoff_mon,
datediff(day, startd, endd) as timeoff,
getdate() as dat,
month(getdate()) as current_mon
from sample s
union all
select null, null, null, null, null, 0, getdate(), datepart(month, getdate())
where not exists (
select 1
from sample s
where
s.startd < dateadd(mm, datediff(mm, 0, getdate()) + 1, 0)
and s.endd >= dateadd(mm, datediff(mm, 0, getdate()), 0)
)
Demo on DB Fiddle:
Name | ID | STARTD | ENDD | timeoff_mon | timeoff | dat | current_mon
:--------- | ---: | :--------- | :--------- | ----------: | ------: | :---------------------- | ----------:
Jack | 5 | 2020-01-25 | 2020-01-26 | 1 | 1 | 2020-03-28 14:28:56.867 | 3
John | 6 | 2020-02-05 | 2020-02-09 | 2 | 4 | 2020-03-28 14:28:56.867 | 3
null | null | null | null | null | 0 | 2020-03-28 14:28:56.867 | 3

Alternative to STRING_AGG in with SQL

I have a table as below
| activityName | UserID | deviceID | createdDate |
|------------------------------------------------------------|
| ON | 1 | adddsad |2020-01-09 00:02:59.477 |
| OFF | 1 | adddsad |2020-01-09 00:50:39.857 |
| ON | 2 | bdddsad |2020-01-09 00:51:11.480 |
| OFF | 2 | bdddsad |2020-01-09 00:51:19.450 |
when I use STRING_AGG like this which is accurate and returns the desired result
SELECT STRING_AGG(activityName + ' - ' + CONVERT(varchar, createdDate), ' | ') AS tag,
deviceID,
UserID
FROM (SELECT tag,
deviceID,
UserID
FROM tbl_DailyLogMaster
WHERE CONVERT(date, createdDate) = CONVERT(date, GETDATE())
GROUP BY userID) a
GROUP BY UserID;
It will return like this
| tag | deviceID | UserID |
|------------------------------------------------------------------------------------|
| ON - 2020-01-09 00:02:59.477 | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| ON - 2020-01-09 00:51:11.480 | OFF - 2020-01-09 00:51:19.450 | bdddsad | 2 |
On production I have SQL Server 2014 running and had to work on alternative for STRING_AGG which is not supported on older version
here is alternative I created
SELECT deviceID,
UserID,
STUFF((SELECT activityName + ' - ' + CONVERT(varchar, createdDate)
FROM tbl_DailyLogMaster
WHERE userID = tbl_DailyLogMaster.UserID
AND CONVERT(date, createdDate) = CONVERT(date, GETDATE())
ORDER BY UserID
FOR XML PATH('')),1,1,'') AS tag
FROM tbl_DailyLogMaster
WHERE CONVERT(date, createdDate) = CONVERT(date, GETDATE())
GROUP BY UserID,
deviceID,
UserID,
createdDate,
activityName;
it returns like this
| tag | deviceID | UserID |
|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | bdddsad | 2 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | bdddsad | 2 |
What I am doing wrong with second query?
A some what blind guess, but I think this is the correct answer. you needed to ensure the subquery was properly correlated:
SELECT deviceID,
UserID,
STUFF((SELECT ' | ' + sq.activityName + ' - ' + CONVERT(varchar(20),sq.createdDate, 0)
FROM tbl_DailyLogMaster sq
WHERE DLM.UserID = sq.UserId
AND DLM.DeviceID = sq.DeviceID
AND sq.createdDate >= CONVERT(date, GETDATE())
AND sq.createdDate < DATEADD(DAY, 1, CONVERT(date, GETDATE()))
ORDER BY CreatedDate
FOR XML PATH(''),TYPE).value('.','varchar(MAX)'),1,3,'') AS tag --As yuou have no leading separator, no need for STUFF
FROM tbl_DailyLogMaster DLM
WHERE DLM.createdDate >= CONVERT(date, GETDATE())
AND DLM.createdDate < DATEADD(DAY, 1, CONVERT(date, GETDATE()))
GROUP BY UserID,
DeviceID;

Get list of counts by date

I have two tables. One containing a list of applications. And another one containing counts associated to them every week. Now I want to get as a result the app name and the count for this week and the previous. Let me explain this.
app:
+----+-------------+
| id | name |
+----+-------------+
| 1 | Office 2007 |
+----+-------------+
| 2 | Office 2010 |
+----+-------------+
| 3 | Office 2013 |
+----+-------------+
count:
+----+--------+-------+------------+
| id | app_id | count | date |
+----+--------+-------+------------+
| 1 | 1 | 200 | 2016-01-11 |
+----+--------+-------+------------+
| 2 | 2 | 500 | 2016-01-11 |
+----+--------+-------+------------+
| 3 | 3 | 750 | 2016-01-11 |
+----+--------+-------+------------+
| 4 | 1 | 180 | 2016-01-18 |
+----+--------+-------+------------+
| 5 | 2 | 378 | 2016-01-18 |
+----+--------+-------+------------+
| 6 | 3 | 1000 | 2016-01-18 |
+----+--------+-------+------------+
And this is the result I need. I need all the applications with the count of this week and the previous:
+-------------+-----------------+-----------------+
| app | count_this_week | count_prev_week |
+-------------+-----------------+-----------------+
| Office 2007 | 180 | 200 |
+-------------+-----------------+-----------------+
| Office 2010 | 378 | 500 |
+-------------+-----------------+-----------------+
| Office 2013 | 1000 | 750 |
+-------------+-----------------+-----------------+
A script runs every week which fills the count table. And now I need to get a report also on a weekly basis.
Honestly I'm a bit lost as I don't know how to declare the conditions for the columns.
You can try to group first by DATEPART(WEEK,C.date),name and then split the counts into 2 columns using another GROUP BY. Something like this
EDIT
If there are exactly 1 record per week per app, you can do with just one group by like this.
SELECT
appname,
SUM(CASE WHEN weekno = 0 THEN sumcount ELSE 0 END) as thisweek,
SUM(CASE WHEN weekno = 1 THEN sumcount ELSE 0 END) as lastweek
FROM
(
SELECT
DATEPART(WEEK,CURRENT_TIMESTAMP) - DATEPART(WEEK,C.date) as weekno,
name as appname,
count as sumcount
FROM App A
INNER JOIN CountTable C ON A.[id] = C.[app_id]
WHERE DATEPART(WEEK,C.date) BETWEEN DATEPART(WEEK,CURRENT_TIMESTAMP) - 1 AND DATEPART(WEEK,CURRENT_TIMESTAMP)
)T
GROUP BY appname
Query
SELECT
appname,
SUM(CASE WHEN weekno = 0 THEN sumcount ELSE 0 END) as thisweek,
SUM(CASE WHEN weekno = 1 THEN sumcount ELSE 0 END) as lastweek
FROM
(
SELECT
DATEPART(WEEK,CURRENT_TIMESTAMP) - DATEPART(WEEK,C.date) as weekno,
name as appname,
SUM(count) as sumcount
FROM App A INNER JOIN CountTable C ON A.[id] = C.[app_id]
WHERE DATEPART(WEEK,C.date) BETWEEN DATEPART(WEEK,CURRENT_TIMESTAMP) - 1 AND DATEPART(WEEK,CURRENT_TIMESTAMP)
GROUP BY DATEPART(WEEK,C.date),name
) AS T
GROUP BY appname
SQL Fiddle
Output
| appname | thisweek | lastweek |
|-------------|----------|----------|
| Office 2007 | 180 | 200 |
| Office 2010 | 378 | 500 |
| Office 2013 | 1000 | 750 |
You can use this generic query with a variable for the current week day:
DECLARE #week date = '2016-01-18';
WITH data AS (
SELECT a.name, c.[count]
, w = CASE WHEN c.[date] = #week THEN 0 ELSE 1 END
FROM #Counts c
INNER JOIN #Apps a ON c.app_id = a.id
WHERE [date] = #week OR [date] = DATEADD(day, -7, #week)
)
SELECT App = name, count_this_week = [0], count_prev_week = [1]
FROM data d
PIVOT (
MAX([count])
FOR w IN ([0], [1])
) p
Output:
App count_this_week count_prev_week
Office 2007 180 200
Office 2010 378 500
Office 2013 1000 750
Your data:
DECLARE #Apps TABLE ([id] int, [name] varchar(11));
DECLARE #Counts TABLE([id] int, [app_id] int, [count] int, [date] date);
INSERT INTO #Apps([id], [name])
VALUES
(1, 'Office 2007'),
(2, 'Office 2010'),
(3, 'Office 2013')
;
INSERT INTO #Counts([id], [app_id], [count], [date])
VALUES
(1, 1, 200, '2016-01-11'),
(2, 2, 500, '2016-01-11'),
(3, 3, 750, '2016-01-11'),
(4, 1, 180, '2016-01-18'),
(5, 2, 378, '2016-01-18'),
(6, 3, 1000, '2016-01-18')
;
SELECT *
FROM count
JOIN app ON app.id=count.app_id
WHERE date BETWEEN '2016-01-18' AND '2016-01-11'

SQL not delivering expected result with RIGHT JOIN

I have been working on this query for some time now, and reading right join question after right join question here on SO, but I cannot figure this one out.
I have the following Query:
DECLARE #ExpectedDateSample VARCHAR(10)
DECLARE #Date datetime
DECLARE #DaysInMonth INT
DECLARE #i INT
--GIVE VALUES
SET #ExpectedDateSample = SUBSTRING(CONVERT(VARCHAR, DATEADD(MONTH, +0, GETDATE()), 112),5,2)+'/'+CONVERT(VARCHAR(4), DATEPART(YEAR, GETDATE()))
SET #Date = Getdate()
SELECT #DaysInMonth = datepart(dd,dateadd(dd,-1,dateadd(mm,1,cast(cast(year(#Date) as varchar)+'-'+cast(month(#Date) as varchar)+'-01' as datetime))))
SET #i = 1
--MAKE TEMP TABLE
CREATE TABLE #TempDays
(
[days] VARCHAR(50)
)
WHILE #i <= #DaysInMonth
BEGIN
INSERT INTO #TempDays
VALUES(#i)
SET #i = #i + 1
END
SELECT DATEPART(DD, CONVERT(DATE, a.budg_tempDODate1, 103)) ExpectedDate, SUM(a.budg_do1_total) ExpectedAmount
FROM CRM.dbo.budget a
RIGHT JOIN #TempDays on DATEPART(DD, CONVERT(DATE, a.budg_tempDODate1, 103)) = #TempDays.days
WHERE DATEPART(MONTH, a.budg_tempDODate1) = DATEPART(MONTH, GetDate()) AND DATEPART(YEAR, a.budg_tempDODate1) = DATEPART(YEAR, GetDate())
GROUP BY a.budg_tempDODate1
--DROP TABLE TO ALLOW CREATION AGAIN
DROP TABLE #TempDays
In my Budget table I have a few days out of the month missing, but that is why I create a Temp table to count all the days of the month. And then RIGHT join to that Temp table.
I am trying to calculate how much cash is expected on each day of the month. If the day does not exist in my budget table, DO NOT leave it out completely, but rather display 0 is expected.
What I am currently getting
+------+---------------+
| DAYS | AMOUNT |
+------+---------------+
| 1 | 34627.000000 |
| 2 | 72474.000000 |
| 3 | 27084.000000 |
| 4 | 9268.000000 |
| 5 | 32304.000000 |
| 6 | 23261.000000 |
| 7 | 5614.000000 |
| 9 | 3464.000000 |
| 10 | 20046.000000 |
| 12 | 7449.000000 |
| 13 | 265163.000000 |
| 14 | 24210.000000 |
| 15 | 68848.000000 |
| 16 | 31702.000000 |
| 17 | 2500.000000 |
| 19 | 2914.000000 |
| 20 | 238406.000000 |
| 21 | 15642.000000 |
| 22 | 2514.000000 |
| 23 | 46521.000000 |
| 24 | 34093.000000 |
| 25 | 899081.000000 |
| 26 | 204085.000000 |
| 27 | 316341.000000 |
| 28 | 48826.000000 |
| 29 | 2657.000000 |
| 30 | 440401.000000 |
+------+---------------+
What I was Expecting:
+------+---------------+
| DAYS | AMOUNT |
+------+---------------+
| 1 | 34627.000000 |
| 2 | 72474.000000 |
| 3 | 27084.000000 |
| 4 | 9268.000000 |
| 5 | 32304.000000 |
| 6 | 23261.000000 |
| 7 | 5614.000000 |
| 8 | NULL |
| 9 | 3464.000000 |
| 10 | 20046.000000 |
| 11 | NULL |
| 12 | 7449.000000 |
| 13 | 265163.000000 |
| 14 | 24210.000000 |
| 15 | 68848.000000 |
| 16 | 31702.000000 |
| 17 | 2500.000000 |
| 18 | NULL |
| 19 | 2914.000000 |
| 20 | 238406.000000 |
| 21 | 15642.000000 |
| 22 | 2514.000000 |
| 23 | 46521.000000 |
| 24 | 34093.000000 |
| 25 | 899081.000000 |
| 26 | 204085.000000 |
| 27 | 316341.000000 |
| 28 | 48826.000000 |
| 29 | 2657.000000 |
| 30 | 440401.000000 |
+------+---------------+
As you can see, the expected result still shows the days Im not expecting any value.
Can Anybody notice anything immediately wrong with my query... Any help and tips would be greatly appreciated.
I'm using SQL server 2008
Thanks!
Mike
Change your where clause to part of the join, and display the day value from #tempdays, not the data table
SELECT
#TempDays.days ExpectedDate, SUM(a.budg_do1_total) ExpectedAmount
FROM CRM.dbo.budget a
RIGHT JOIN #TempDays on
DATEPART(DD, CONVERT(DATE, a.budg_tempDODate1, 103)) = #TempDays.days
AND DATEPART(MONTH, a.budg_tempDODate1) = DATEPART(MONTH, GetDate())
AND DATEPART(YEAR, a.budg_tempDODate1) = DATEPART(YEAR, GetDate())
GROUP BY #TempDays.days
The problem is your Where Clause -
WHERE DATEPART(MONTH, a.budg_tempDODate1) = DATEPART(MONTH, GetDate()) AND DATEPART(YEAR, a.budg_tempDODate1) = DATEPART(YEAR, GetDate())
The where clause and the group by clauses are applied on the table with less data.
So, the result set is getting confined to the table with less data ignoring the join clauses.
I have rewritten this and tested it.
declare #budget table
(
budg_tempDODate1 datetime,
budg_do1_total float
)
insert into #budget(budg_tempDODate1, budg_do1_total)
select '2014-06-01', 25
union select '2014-06-01', 23
union select '2014-06-02', 23
union select '2014-06-02', 23
union select '2014-06-02', 23
union select '2014-06-03', 23
union select '2014-06-04', 23
union select '2014-06-05', 23
union select '2014-06-05', 23
union select '2014-06-05', 23
union select '2014-06-06', 23
union select '2014-06-07', 23
union select '2014-06-08', 23
union select '2014-06-09', 23
union select '2014-06-10', 23
DECLARE #ExpectedDateSample VARCHAR(10)
DECLARE #Date datetime
DECLARE #DaysInMonth INT
DECLARE #i INT
--GIVE VALUES
SET #ExpectedDateSample = SUBSTRING(CONVERT(VARCHAR, DATEADD(MONTH, +0, GETDATE()), 112),5,2)+'/'+CONVERT(VARCHAR(4), DATEPART(YEAR, GETDATE()))
SET #Date = Getdate()
SELECT #DaysInMonth = datepart(dd,dateadd(dd,-1,dateadd(mm,1,cast(cast(year(#Date) as varchar)+'-'+cast(month(#Date) as varchar)+'-01' as datetime))))
SET #i = 1
--MAKE TEMP TABLE
CREATE TABLE #TempDays
(
[days] int
)
WHILE #i <= #DaysInMonth
BEGIN
INSERT INTO #TempDays
VALUES(#i)
SET #i = #i + 1
END
--select * from #TempDays
SELECT
td.days as ExpectedDate,
SUM(isnull(a.budg_do1_total, 0)) ExpectedAmount
FROM
--CRM.dbo.budget a
#TempDays td
left outer JOIN #budget a on
DATEPART(MONTH, a.budg_tempDODate1) = DATEPART(MONTH, GetDate())
AND DATEPART(YEAR, a.budg_tempDODate1) = DATEPART(YEAR, GetDate())
AND DATEPART(DD, CONVERT(DATE, a.budg_tempDODate1, 103)) = td.days
GROUP BY
--a.budg_tempDODate1
td.days
--DROP TABLE TO ALLOW CREATION AGAIN
DROP TABLE #TempDays
Here is the sql fiddle

Sub CTE or Nested Model

I have a string variable with month and year. This can be multiple seperated with comma. I need to get all the dates of all months in the string
Eg: IF my String have '2014-01,2014-02' I need to return 01-01-2014, 02-01-2014 etc like all days in january and also all dates in february.
I tried like below
DECLARE #myString as NVARCHAR(2000) = '2014-03,2014-04'
;with cte1
as (
SELECT
CAST(
CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +
RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)
AS DATE) AS StartDate
,CONVERT(DATE,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,CAST(
CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +
RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)
AS DATETIME))+1,0))) AS EndDate
FROM dbo.Split(myString , ',')
),
cte2
AS
(
SELECT StartDate, EndDate FROM cte1
UNION ALL
SELECT CONVERT(DATE, DATEADD(DAY,1 , StartDate)), CONVERT(DATE, DATEADD(DAY,1 , StartDate)) FROM cte2
WHERE CONVERT(DATE, DATEADD(DAY,1 , StartDate)) < EndDate
)
SELECT * FROM cte2
In the first cte i will return 2 rows with start date of the month and end date of the month. So i need to loop all the days in each row of the first cte
I have the work around with 2 seperate queries
-- To get the month start and end date
;with cte1
as (
SELECT
CAST(
CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +
RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)
AS DATE) AS StartDate
,CONVERT(DATE,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,CAST(
CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +
RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)
AS DATETIME))+1,0))) AS EndDate
FROM dbo.Split(#CompareMonths, ',')
)
--To get all days between start and end date (Current month)
Declare #startdate date = CONVERT(DATE, DATEADD(dd, -DAY(DATEADD(MONTH, 0, GETDATE())) + 1, DATEADD(MONTH, 0, GETDATE())))
Declare #endDate date = DATEADD(DAY, -DAY(DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))
;With cte
as
(
SELECT #startdate sDate
UNION All
SELECT DATEADD(day,1,sDate) FROM cte WHERE DATEADD(day,1,sDate) <= #endDate
)
select * from cte
I need to join this 2 concepts so that from the string i got all the days of all the months i passed
With the help of a numbers table and a splistring function.
SQL Fiddle
MS SQL Server 2012 Schema Setup:
create table dbo.Number(N int primary key);
go
insert into dbo.Number(N)
select top(11000) row_number() over(order by 1/0) - 1
from sys.all_objects as o1, sys.all_objects as o2
go
create function [dbo].[SplitString](#List nvarchar(max), #Delimiter nvarchar(255)) returns table
with schemabinding
as
return
(
select substring(#List, N, charindex(#Delimiter, #List + #Delimiter, N) - N) as Item
from dbo.Number
where N <= convert(int, len(#List)) and
substring(#Delimiter + #List, N, len(#Delimiter)) = #Delimiter
);
Query 1:
declare #S nvarchar(max) = '2014-01,2014-02'
select T2.D
from dbo.SplitString(#S, N',') as S
cross apply (select cast(S.Item+'-01' as date)) as T1(D)
cross apply (
select dateadd(day, N.N, T1.D)
from Number as N
where N between 0 and datediff(day, T1.D, eomonth(T1.D))
) as T2(D)
Results:
| D |
|------------|
| 2014-01-01 |
| 2014-01-02 |
| 2014-01-03 |
| 2014-01-04 |
| 2014-01-05 |
| 2014-01-06 |
| 2014-01-07 |
| 2014-01-08 |
| 2014-01-09 |
| 2014-01-10 |
| 2014-01-11 |
| 2014-01-12 |
| 2014-01-13 |
| 2014-01-14 |
| 2014-01-15 |
| 2014-01-16 |
| 2014-01-17 |
| 2014-01-18 |
| 2014-01-19 |
| 2014-01-20 |
| 2014-01-21 |
| 2014-01-22 |
| 2014-01-23 |
| 2014-01-24 |
| 2014-01-25 |
| 2014-01-26 |
| 2014-01-27 |
| 2014-01-28 |
| 2014-01-29 |
| 2014-01-30 |
| 2014-01-31 |
| 2014-02-01 |
| 2014-02-02 |
| 2014-02-03 |
| 2014-02-04 |
| 2014-02-05 |
| 2014-02-06 |
| 2014-02-07 |
| 2014-02-08 |
| 2014-02-09 |
| 2014-02-10 |
| 2014-02-11 |
| 2014-02-12 |
| 2014-02-13 |
| 2014-02-14 |
| 2014-02-15 |
| 2014-02-16 |
| 2014-02-17 |
| 2014-02-18 |
| 2014-02-19 |
| 2014-02-20 |
| 2014-02-21 |
| 2014-02-22 |
| 2014-02-23 |
| 2014-02-24 |
| 2014-02-25 |
| 2014-02-26 |
| 2014-02-27 |
| 2014-02-28 |
Ref: Split strings the right way – or the next best way