I know that there are many questions on this topic, but no one seem to works for my problem
Shortly, I want to merge horizontal an unknown number of result sets as in the following example
Result 1:
Name |sum1 |sum2
________________
name1| 0.5 |0.1
name2| 0.6 |0.2
Result 2:
Name |sum1 |sum2
________________
name1| 1.5 |0.7
name2| 1.6 |0.9
.
.
.
Result n:
Name |sum1 |sum2
________________
name1| 7.5 |9.7
name2| 8.6 |5.9
Finally :
Name |sum1 |sum2| sum1 | sum2|.......| sum1|sum2
________________________________________
name1| 0.5 |0.1 | 1.5 | 0.7 |.......| 7.5 |9.7
name2| 0.6 |0.2 | 1.6 | 0.9 |.......| 8.6 |5.9
The column "Name" is exactly the same in all of the result.
Think you guys could help out?
You would use join:
select r1.name, r1.sum1, r1.sum2, r2.sum1, r2.sum2, r3.sum1, r3.sum2
from result1 r1 join
result2 r2
on r1.name = r2.name join
results r3
on r1.name = r3.name
You would need to continue this for each result set.
Now, having an unknown number of result sets makes this more complicated. That simply requires generating a dynamic SQL statement, based on the same logic.
Quick stored procedure to dynamically build your query string and execute it. You can control the execute with the first input #in_run_query.
CREATE PROCEDURE dynamic_sql_query
#in_run_query INT
, #in_count_results_sets INT
AS
BEGIN
IF #in_count_results_sets IS NULL
EXIT
IF TRY_CONVERT(INT,#in_count_results_sets) IS NULL
EXIT
IF #in_count_results_sets < 2
BEGIN
SELECT 'Counter must be between 2 and 100'
EXIT
END
IF #in_count_results_sets > 100
BEGIN
SELECT 'Build a better database'
EXIT
END
DECLARE #sql_string NVARCHAR(MAX) , #counter INT = 2
SET #select = 'SELECT r1.name, r1.sum1, r1.sum2'
SET #from = 'FROM result1 AS r1'
LOOP:
SET #prefix = 'r' + CAST(#counter AS String)
SET #full_name = 'result' + CAST(#counter AS String)
-- select
SET #select = #select + ', ' + #prefix + '.name, ' + #prefix + '.sum1, ' + #prefix + '.sum2'
-- from
SET #from = #from + ' join ' + #full_name + ' AS ' + #prefix + ' on r1.name = ' + #prefix + '.name'
IF #counter = #in_count_results_sets
GOTO AppendStrings
#counter = #counter + 1
GOTO LOOP
AppendStrings:
SET #sql_string = #select + ' ' + #from + ';'
IF #in_run_query <> 1
BEGIN
SELECT #sql_string
EXIT
END
EXECUTE sp_executesql #sql_string
END
My print statement fails each time and so does my exec, anytime I try to run this statement it just tells me command completed successfully. I added the print statement to try to see what was actually being executed, but I am still mind-blown on this. Can someone here please help me?
Shouldn't the Print statement at least show me what I am trying to run? If I print each variable individually before trying to run the update it shows the correct value, so I can only assume it is something way wrong with my update statement?
Declare #fulldata varchar(30), #rsi varchar(50), #employeename varchar(50), #email varchar(50), #rsi2 varchar(50), #email2 varchar(50),
#rsiID varchar(50), #calldate datetime, #calltime datetime, #orderdate datetime, #email3 varchar(50), #uniqueID int, #sql varchar(max)
Set #fullData = 'tvdb'
Set #rsi = 'Alphabet'
Set #employeename = 'Mike Jones'
Set #email = '123abc#gmail.com'
Set #rsi2 = 'Broccoli'
Set #email2 = 'abc123#gmail.com'
Set #rsiID = 'alt16bc'
Set #calldate = '06/15/2015'
Set #calltime = '12:15:00'
Set #orderdate = '06/16/2015'
Set #email3 = 'pineapple1841#gmail.com'
Set #uniqueID = 172855
Set #sql =
'update '+#fulldata+' '
+ 'set rsi = COALESCE('''+#rsi+''',''''), '
+ 'employeename = COALESCE('''+#employeename+''',''''), '
+ 'email = COALESCE('''+#email+''',''''), '
+ 'rsi2 = COALESCE('''+#rsi2+''',''''), '
+ 'email2 = COALESCE('''+#email2+''',''''), '
+ 'rsiID = COALESCE('''+#rsiID+''',''''), '
+ 'calldate = COALESCE('''+CAST(#calldate As Varchar)+''',''''), '
+ 'calltime = COALESCE('''+CAST(#calltime As Varchar)+''',''''), '
+ 'orderdate = COALESCE('''+CAST(#orderdate As Varchar)+''',''''), '
+ 'email3 = COALESCE('''+#email3+''','''') '
+ 'where uniqueID = '+CAST(#uniqueID As Varchar)+' and '+CAST(#uniqueID As Varchar)+' > 0 '
Print #sql
exec (#sql)
EDIT ---
If I try to insert my statements into a table to check it is null. Which leads me to why is #sql not being assigned?
Insert Into #SqlStatement (sql12) VALUES (#sql)
Select * FROM #SqlStatement
Are you sure you have all lines included here? and you can run it without error?
At least your don't have declaration of #sql.
Even you declare the #sql, this line will give you error:
Set uniqueID = 172855
It should be
Set #uniqueID = 172855
Without assigning values to #uniqueID, your whole #sql is be NULL and print will generate NO output.
update tvdb set rsi = COALESCE('Alphabet',''), employeename = COALESCE('Mike Jones',''), email = COALESCE('123abc#gmail.com',''), rsi2 = COALESCE('Broccoli',''), email2 = COALESCE('abc123#gmail.com',''), rsiID = COALESCE('alt16bc',''), calldate = COALESCE('Jun 15 2015 12:00AM',''), calltime = COALESCE('Jan 1 1900 12:15PM',''), orderdate = COALESCE('Jun 16 2015 12:00AM',''), email3 = COALESCE('pineapple1841#gmail.com','') where uniqueID = 172855 and 172855 > 0
Msg 208, Level 16, State 1, Line 1
Invalid object name 'tvdb'.
To debug your code, you can comment out some lines like:
Set #sql =
'update '+#fulldata+' '
+ 'set rsi = COALESCE('''+#rsi+''',''''), '
---+ 'employeename = COALESCE('''+#employeename+''',''''), '
----+ 'email = COALESCE('''+#email+''',''''), '
----+ 'rsi2 = COALESCE('''+#rsi2+''',''''), '
----+ 'email2 = COALESCE('''+#email2+''',''''), '
----+ 'rsiID = COALESCE('''+#rsiID+''',''''), '
----+ 'calldate = COALESCE('''+CAST(#calldate As Varchar)+''',''''), '
----+ 'calltime = COALESCE('''+CAST(#calltime As Varchar)+''',''''), '
----+ 'orderdate = COALESCE('''+CAST(#orderdate As Varchar)+''',''''), '
----+ 'email3 = COALESCE('''+#email3+''','''') '
----+ 'where uniqueID = '+CAST(#uniqueID As Varchar)+' and '+CAST(#uniqueID As Varchar)+' > 0 '
Print #sql
exec (#sql)
and uncomment one line a time until you find the problematic line.
To catch values and make sure you have a non-null #sql, you need use the COALESCE this way:
Set #sql =
'update '+#fulldata+' ' ...
+ 'email = '''+COALESCE(#email,'')+''','
I am looking to extract "human readable" schedule information from the ReportServer.dbo.Schedule table using t-sql.
An example of "human readable" follows.
At 6:02 AM every Sun, Mon, Tue, Wed, Thu, Fri, Sat of every week, starting 2/28/2011
There are a bunch of numeric fields in the table which are used to store the schedule, but I would like to convert those to words, as in my example.
Has anyone ever done this with reporting services?
SQL is not great for string manipulation or bitwise operations, and parsing this table requires a moderate bit of both. I'm sure SSRS doesn't do this in SQL: I probably could have written this in half the time and half the lines in C#.
USE ReportServer;
WITH EnhancedSched
AS (
SELECT
dbo.Schedule.ScheduleID ,
dbo.Schedule.Name ,
dbo.Schedule.StartDate ,
dbo.Schedule.Flags ,
dbo.Schedule.NextRunTime ,
dbo.Schedule.LastRunTime ,
dbo.Schedule.EndDate ,
dbo.Schedule.RecurrenceType ,
dbo.Schedule.MinutesInterval ,
dbo.Schedule.DaysInterval ,
dbo.Schedule.WeeksInterval ,
dbo.Schedule.DaysOfWeek ,
dbo.Schedule.DaysOfMonth ,
dbo.Schedule.Month ,
dbo.Schedule.MonthlyWeek ,
dbo.Schedule.State ,
dbo.Schedule.LastRunStatus ,
dbo.Schedule.ScheduledRunTimeout ,
dbo.Schedule.CreatedById ,
dbo.Schedule.EventType ,
dbo.Schedule.EventData ,
dbo.Schedule.Type ,
dbo.Schedule.ConsistancyCheck ,
dbo.Schedule.Path ,
CASE WHEN DaysOfWeek & 1 <> 0 THEN 'Sun, '
ELSE ''
END + CASE WHEN DaysOfWeek & 2 <> 0 THEN 'Mon, '
ELSE ''
END + CASE WHEN DaysOfWeek & 4 <> 0 THEN 'Tue, '
ELSE ''
END + CASE WHEN DaysOfWeek & 8 <> 0 THEN 'Wed, '
ELSE ''
END
+ CASE WHEN DaysOfWeek & 16 <> 0 THEN 'Thu, '
ELSE ''
END + CASE WHEN DaysOfWeek & 32 <> 0 THEN 'Fri, '
ELSE ''
END + CASE WHEN DaysOfWeek & 64 <> 0 THEN 'Sat, '
ELSE ''
END AS DaysOfWeekString ,
CASE WHEN DaysOfMonth & 1 <> 0 THEN '1,'
ELSE ''
END + CASE WHEN DaysOfMonth & 2 <> 0 THEN '2,'
ELSE ''
END + CASE WHEN DaysOfMonth & 4 <> 0 THEN '3,'
ELSE ''
END + CASE WHEN DaysOfMonth & 8 <> 0 THEN '4,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 16 <> 0 THEN '5,'
ELSE ''
END + CASE WHEN DaysOfMonth & 32 <> 0 THEN '6,'
ELSE ''
END + CASE WHEN DaysOfMonth & 64 <> 0 THEN '7,'
ELSE ''
END + CASE WHEN DaysOfMonth & 128 <> 0 THEN '8,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 256 <> 0 THEN '9,'
ELSE ''
END + CASE WHEN DaysOfMonth & 512 <> 0 THEN '10,'
ELSE ''
END + CASE WHEN DaysOfMonth & 1024 <> 0 THEN '11,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 2048 <> 0 THEN '12,'
ELSE ''
END + CASE WHEN DaysOfMonth & 4096 <> 0 THEN '13,'
ELSE ''
END + CASE WHEN DaysOfMonth & 8192 <> 0 THEN '14,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 16384 <> 0 THEN '15,'
ELSE ''
END + CASE WHEN DaysOfMonth & 32768 <> 0 THEN '16,'
ELSE ''
END + CASE WHEN DaysOfMonth & 65536 <> 0 THEN '17,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 131072 <> 0 THEN '18,'
ELSE ''
END + CASE WHEN DaysOfMonth & 262144 <> 0 THEN '19,'
ELSE ''
END + CASE WHEN DaysOfMonth & 524288 <> 0 THEN '20,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 1048576 <> 0 THEN '21,'
ELSE ''
END + CASE WHEN DaysOfMonth & 2097152 <> 0 THEN '22,'
ELSE ''
END + CASE WHEN DaysOfMonth & 4194304 <> 0 THEN '23,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 8388608 <> 0 THEN '24,'
ELSE ''
END + CASE WHEN DaysOfMonth & 16777216 <> 0 THEN '25,'
ELSE ''
END + CASE WHEN DaysOfMonth & 33554432 <> 0 THEN '26,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 67108864 <> 0 THEN '27,'
ELSE ''
END + CASE WHEN DaysOfMonth & 134217728 <> 0 THEN '28,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 268435456 <> 0 THEN '29,'
ELSE ''
END + CASE WHEN DaysOfMonth & 536870912 <> 0 THEN '30,'
ELSE ''
END
+ CASE WHEN DaysOfMonth & 1073741824 <> 0 THEN '31,'
ELSE ''
END AS DaysOfMonthString ,
CASE WHEN Month = 4095 THEN 'every month, '
ELSE CASE WHEN Month & 1 <> 0 THEN 'Jan, '
ELSE ''
END + CASE WHEN Month & 2 <> 0 THEN 'Feb, '
ELSE ''
END + CASE WHEN Month & 4 <> 0 THEN 'Mar, '
ELSE ''
END
+ CASE WHEN Month & 8 <> 0 THEN 'Apr, '
ELSE ''
END + CASE WHEN Month & 16 <> 0 THEN 'May, '
ELSE ''
END + CASE WHEN Month & 32 <> 0 THEN 'Jun, '
ELSE ''
END
+ CASE WHEN Month & 64 <> 0 THEN 'Jul, '
ELSE ''
END + CASE WHEN Month & 128 <> 0 THEN 'Aug, '
ELSE ''
END
+ CASE WHEN Month & 256 <> 0 THEN 'Sep, '
ELSE ''
END + CASE WHEN Month & 512 <> 0 THEN 'Oct, '
ELSE ''
END
+ CASE WHEN Month & 1024 <> 0 THEN 'Nov, '
ELSE ''
END + CASE WHEN Month & 2048 <> 0 THEN 'Dec, '
ELSE ''
END
END AS MonthString ,
CASE MonthlyWeek
WHEN 1 THEN 'first'
WHEN 2 THEN 'second'
WHEN 3 THEN 'third'
WHEN 4 THEN 'fourth'
WHEN 5 THEN 'last'
END AS MonthlyWeekString ,
' starting ' + CONVERT (VARCHAR, StartDate, 101)
+ CASE WHEN EndDate IS NOT NULL
THEN ' and ending ' + CONVERT (VARCHAR, EndDate, 101)
ELSE ''
END AS StartEndString ,
CASE CONVERT(VARCHAR, DATEPART(HOUR, StartDate) % 12)
WHEN 0 THEN '12'
ELSE CONVERT(VARCHAR, DATEPART(HOUR, StartDate) % 12)
END + ':'
+ CASE WHEN DATEPART(MINUTE, StartDate) < 10
THEN '0' + CONVERT(VARCHAR(2), DATEPART(MINUTE,
StartDate))
ELSE CONVERT(VARCHAR(2), DATEPART(MINUTE, StartDate))
END + CASE WHEN DATEPART(HOUR, StartDate) >= 12 THEN ' PM'
ELSE ' AM'
END AS StartTime
FROM
Schedule
),
SuperEnhancedSchedule
AS (
SELECT
EnhancedSched.ScheduleID ,
EnhancedSched.Name ,
EnhancedSched.StartDate ,
EnhancedSched.Flags ,
EnhancedSched.NextRunTime ,
EnhancedSched.LastRunTime ,
EnhancedSched.EndDate ,
EnhancedSched.RecurrenceType ,
EnhancedSched.MinutesInterval ,
EnhancedSched.DaysInterval ,
EnhancedSched.WeeksInterval ,
EnhancedSched.DaysOfWeek ,
EnhancedSched.DaysOfMonth ,
EnhancedSched.Month ,
EnhancedSched.MonthlyWeek ,
EnhancedSched.State ,
EnhancedSched.LastRunStatus ,
EnhancedSched.ScheduledRunTimeout ,
EnhancedSched.CreatedById ,
EnhancedSched.EventType ,
EnhancedSched.EventData ,
EnhancedSched.Type ,
EnhancedSched.ConsistancyCheck ,
EnhancedSched.Path , -- spec what you need.
CASE WHEN RecurrenceType = 1
THEN 'At ' + StartTime + ' on '
+ CONVERT(VARCHAR, StartDate, 101)
WHEN RecurrenceType = 2
THEN 'Every ' + CONVERT(VARCHAR, ( MinutesInterval / 60 ))
+ ' hour(s) and '
+ CONVERT(VARCHAR, ( MinutesInterval % 60 ))
+ ' minute(s), ' + 'starting '
+ CONVERT (VARCHAR, StartDate, 101) + ' at '
+ SUBSTRING(CONVERT(VARCHAR, StartDate, 8), 0, 6)
+ ' ' + SUBSTRING(CONVERT(VARCHAR, StartDate, 109),
25, 2)
+ CASE WHEN EndDate IS NOT NULL
THEN ' and ending '
+ CONVERT (VARCHAR, EndDate, 101)
ELSE ''
END
WHEN RecurrenceType = 3
THEN 'At ' + StartTime + ' every '
+ CASE DaysInterval
WHEN 1 THEN 'day, '
ELSE CONVERT(VARCHAR, DaysInterval) + ' days, '
END + StartEndString
WHEN RecurrenceType = 4
THEN 'At ' + StartTime + ' every '
+ CASE WHEN LEN(DaysOfWeekString) > 1
THEN LEFT(DaysOfWeekString,
LEN(DaysOfWeekString) - 1)
ELSE ''
END + ' of every '
+ CASE WHEN WeeksInterval = 1 THEN ' week,'
ELSE CONVERT(VARCHAR, WeeksInterval)
+ ' weeks,'
END + StartEndString
WHEN RecurrenceType = 5
THEN 'At ' + StartTime + ' on day(s) '
+ CASE WHEN LEN(DaysOfMonthString) > 1
THEN LEFT(DaysOfMonthString,
LEN(DaysOfMonthString) - 1)
ELSE ''
END + ' of ' + MonthString + StartEndString
WHEN RecurrenceType = 6
THEN 'At ' + StartTime + ' on the ' + MonthlyWeekString
+ ' '
+ CASE WHEN LEN(DaysOfWeekString) > 1
THEN LEFT(DaysOfWeekString,
LEN(DaysOfWeekString) - 1)
ELSE ''
END + ' of ' + MonthString + StartEndString
ELSE 'At ' + SUBSTRING(CONVERT(VARCHAR, StartDate, 8), 0,
6) + ' '
+ SUBSTRING(CONVERT(VARCHAR, StartDate, 109), 25, 2)
+ StartEndString
END ScheduleTextDefinition
FROM
EnhancedSched
)
SELECT
*
-- This has the same columns as the native [dbo].Schedule table plus a field called "SheduleTextDefinition"
-- You can use "SuperEnhancedSchedule" in place of the usual SSRS.Schedule table, joining to subscriptions and such.
FROM
SuperEnhancedSchedule
This post may be very old, but it helped me out today!
I found 2 items that I would like to add in the excellent post above by Jamie F for his CTE.
There was a missing entry for day 31 that needs to be added in as part of the EnhancedSched CTE, the below needs to be added to the end of the 'DaysOfMonthString'
+ CASE WHEN DaysOfMonth & 1073741824 <> 0 THEN '31,' ELSE '' END
Also, the 'StartTime' column definition with the modulo 12 makes any time beginning with 12 a zero, so the plain English result shows a start time of 0:30 PM for something that is supposed to say 12:30 pm.
Replace the
CONVERT(VARCHAR, DATEPART(hour, StartDate) % 12)
with
CASE CONVERT(VARCHAR, DATEPART(hour, StartDate) % 12) WHEN 0 THEN '12' ELSE CONVERT(VARCHAR, DATEPART(hour, StartDate) % 12) END
to get the plain English start time to read properly.
Mega thanks to Jamie F's post above, saved my bacon. +1 internets for you good sir.
Sorry for the extra 'answer' post, no rep to comment to up-vote Jamie F's excellent post above.
There's actually a stored procedure in the MSDB database called sp_get_schedule_description that can generate the schedule descriptions. I have the code below writting the schedule ID and the human-readable description to a ScheduleInfo user table. It works very well but the user running the code will need read-access to the msdb database and execute permissions to the SP for it to work.
DECLARE #schedule_description NVARCHAR(255)
DECLARE #freq_type INT
DECLARE #freq_interval INT
DECLARE #freq_subday_type INT
DECLARE #freq_subday_interval INT
DECLARE #freq_relative_interval INT
DECLARE #freq_recurrence_factor INT
DECLARE #active_start_date INT
DECLARE #active_end_date INT
DECLARE #active_start_time INT
DECLARE #active_end_time INT
DECLARE #schedule_id_as_char VARCHAR(10)
DECLARE #scheduleID UNIQUEIDENTIFIER
DECLARE #resultCursor CURSOR
-- Create cursor using records from job schedules in MSDB database
--
SET #resultCursor = CURSOR FOR
SELECT
d.freq_type
,d.freq_interval
,d.freq_subday_type
,d.freq_subday_interval
,d.freq_relative_interval
,d.freq_recurrence_factor
,d.active_start_date
,d.active_end_date
,d.active_start_time
,d.active_end_time
,a.ScheduleID
FROM ReportServer.dbo.Schedule a
JOIN msdb.dbo.sysjobs b on CONVERT(NVARCHAR(128),a.ScheduleID) = b.name
JOIN msdb.dbo.sysjobschedules c on b.job_id = c.job_id
JOIN msdb.dbo.sysschedules d on c.schedule_id = d.schedule_id
OPEN #resultCursor
-- Fetch first record from cursor
--
FETCH NEXT
FROM #resultCursor INTO
#freq_type
,#freq_interval
,#freq_subday_type
,#freq_subday_interval
,#freq_relative_interval
,#freq_recurrence_factor
,#active_start_date
,#active_end_date
,#active_start_time
,#active_end_time
,#scheduleID
-- Loop through cursor and get the rest of the records
--
WHILE ##FETCH_STATUS = 0
BEGIN
-- Call stored prc in MSDB database to get schedule description
--
EXECUTE msdb.dbo.sp_get_schedule_description
#freq_type,
#freq_interval,
#freq_subday_type,
#freq_subday_interval,
#freq_relative_interval,
#freq_recurrence_factor,
#active_start_date,
#active_end_date,
#active_start_time,
#active_end_time,
#schedule_description OUTPUT
-- Insert record to ScheduleInfo table
--
INSERT INTO ScheduleInfo VALUES (#scheduleID, #schedule_description)
-- Get the next record from the cursor
--
FETCH NEXT
FROM #resultCursor INTO
#freq_type
,#freq_interval
,#freq_subday_type
,#freq_subday_interval
,#freq_relative_interval
,#freq_recurrence_factor
,#active_start_date
,#active_end_date
,#active_start_time
,#active_end_time
,#scheduleID
END
--Close cursor
--
CLOSE #resultCursor
DEALLOCATE #resultCursor
I have a solution for this as it came up for a report I am writing.
create function [dbo].[calendarlist](#Value_in as int,#Type as int) returns varchar(200)
as
begin
/*
This code is to work out either the day of the week or the name of a month when given a value
Wrriten by S Manson.
31/01/2012
*/
declare #strings as varchar(200)
declare #Count int
if #Type = 2 --Months
Begin
set #Count =12
end
else if #Type = 1 --Days of Week
Begin
Set #Count = 7
End
else --Days of Month
Begin
Set #Count = 31
End
set #strings = ''
while #Count<>0
begin
if #Value_in>=(select power(2,#count-1))
begin
set #Value_in = #Value_in - (select power(2,#count-1))
If #Type=2
Begin
set #strings = (SELECT DATENAME(mm, DATEADD(month, #count-1, CAST('2008-01-01' AS datetime)))) + ',' + #strings
end
else if #Type = 1
begin
set #strings = (SELECT DATENAME(dw, DATEADD(day, #count-1, CAST('2012-01-01' AS datetime)))) + ',' + #strings
end
else
begin
set #strings = convert(varchar(2),#Count) + ', ' + #strings
end
end
set #count = #count-1
end
if right(#strings,1)=','
set #strings = left(#strings,len(#strings)-1)
return #strings
end