sql server 2008 CTE Bucket filling - sql-server-2008

I found below bucket filling query, however I want to extend this from using single filler value to able to use a filler table. Please see the query with sample data, all I want to be able to join my filler table and recursion to work as is, currently I am picking single item from filler.
Please have a look at this thread to have full context of this problem. http://www.sqlservercentral.com/Forums/Topic568498-338-1.aspx
Thank you.
DECLARE #Buckets TABLE
(
bucketID INT ,
FullCapacity INT ,
currentamount INT
);
DECLARE #Filler TABLE ( ID INT, Filler INT );
INSERT INTO #Buckets
VALUES ( '1', 85, 0 ) ,
( '2', 80, 0 ) ,
( '3', 75, 0 ) ,
( '4', 70, 0 ) ,
( '5', 50, 0 ) ,
( '6', 40, 0 );
INSERT INTO #Filler
VALUES ( '1', 90 ) ,
( '2', 40 ) ,
( '3', 70 ) ,
( '4', 50 ) ,
( '5', 40 ) ,
( '6', 30 ) ,
( '7', 35 );
DECLARE #AmountToAllocate INT = ( SELECT TOP 1
Filler
FROM #Filler
);
--single filler amount
;WITH Calculator
AS ( SELECT bucketID ,
FullCapacity ,
currentamount ,
AmountLeftToAllocate = CASE WHEN #AmountToAllocate > ( FullCapacity
- currentamount )
THEN #AmountToAllocate
- ( FullCapacity
- currentamount )
WHEN #AmountToAllocate < 0
AND ABS(#AmountToAllocate) > currentamount
THEN currentamount
+ #AmountToAllocate
ELSE 0
END ,
NewAmount = CASE WHEN #AmountToAllocate > ( FullCapacity
- currentamount )
THEN FullCapacity
WHEN #AmountToAllocate < 0
AND ABS(#AmountToAllocate) > currentamount
THEN 0
ELSE currentamount
+ #AmountToAllocate
END
FROM #Buckets
WHERE bucketID = 1
UNION ALL
SELECT tr.bucketID ,
tr.FullCapacity ,
tr.currentamount ,
AmountLeftToAllocate = CASE WHEN lr.AmountLeftToAllocate > ( tr.FullCapacity
- tr.currentamount )
THEN lr.AmountLeftToAllocate
- ( tr.FullCapacity
- tr.currentamount )
WHEN lr.AmountLeftToAllocate < 0
AND ABS(lr.AmountLeftToAllocate) > tr.currentamount
THEN tr.currentamount
+ lr.AmountLeftToAllocate
ELSE 0
END ,
NewAmount = CASE WHEN lr.AmountLeftToAllocate > ( tr.FullCapacity
- tr.currentamount )
THEN tr.FullCapacity
WHEN lr.AmountLeftToAllocate < 0
AND ABS(lr.AmountLeftToAllocate) > tr.currentamount
THEN 0
ELSE tr.currentamount
+ lr.AmountLeftToAllocate
END
FROM #Buckets tr
INNER JOIN Calculator lr ON lr.bucketID + 1 = tr.bucketID
)
SELECT bucketID ,
FullCapacity ,
Amount = NewAmount ,
OldAmount = currentamount
FROM Calculator;

In SQL 2012, but still trying to find a solution in SQL 2008.
DROP TABLE #Buckets
CREATE TABLE #Buckets (bucketID INT, FullCapacity INT, CurrentAmount INT);
INSERT INTO #Buckets
VALUES ( '1', 85, 0 ) ,
( '2', 80, 0 ) ,
( '3', 75, 0 ) ,
( '4', 70, 0 ) ,
( '5', 50, 0 ) ,
( '6', 40, 0 );
DROP TABLE #Filler
CREATE TABLE #Filler (FillerID INT, Filler INT);
INSERT INTO #Filler
VALUES ( '1', 90 ) ,
( '2', 40 ) ,
( '3', 70 ) ,
( '4', 50 ) ,
( '5', 40 ) ,
( '6', 30 ) ,
( '7', 35 );
WITH ProcessedDebits AS (
SELECT bucketID, FullCapacity, [from] = ([to] - FullCapacity), [to]
FROM (SELECT *, [to] = SUM(FullCapacity) OVER (PARTITION BY 1 ORDER BY bucketID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM #Buckets) d
),
ProcessedCredits AS (
SELECT FillerID, Filler, [from] = ([to] - Filler), [to]
FROM (SELECT *, [to] = SUM(Filler) OVER (PARTITION BY 1 ORDER BY FillerID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM #Filler) d
)
SELECT
bucketID, FullCapacity,
DebitBalance = CASE
WHEN dr.[to] >= cr.[to] THEN (dr.[to] - cr.[to])
WHEN dr.[to] < cr.[to] THEN 0
ELSE dr.[to] - MAX(cr.[to]) OVER(PARTITION BY 1 ORDER BY dr.bucketID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
END,
FillerID, Filler,
CreditBalance = CASE
WHEN cr.[to] >= dr.[to] THEN (cr.[to] - dr.[to])
WHEN cr.[to] < dr.[to] THEN 0
ELSE cr.[to] - MAX(dr.[to]) OVER(PARTITION BY 1 ORDER BY cr.FillerID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
END
FROM ProcessedDebits dr
FULL OUTER JOIN ProcessedCredits cr
ON cr.[from] < dr.[to]
AND cr.[to] > dr.[from]
ORDER BY bucketID, FillerID
OPTION (MAXDOP 1);

Related

How to conver this SQL server Function into a CTE in snowflake

I have two functions in SQL server that i'm trying to recreate in snowflake. i want to make it a CTE instead as i'm having many issues with it being a function (very picky about date parameters passed through)
I'm not quite thinking of it in the right way. So we pass two paramters through, a date and an int. and the function returns an INT value for us. I'm kind of "stuck".
--Function 1: Straight from SQL server
ALTER FUNCTION [dbo].[cfn_GetShiftIDFromDateTime] (
#dateTime datetime,
#shiftCalendarID int
)
RETURNS int
AS
BEGIN
DECLARE
#time time = CONVERT( time, #dateTime ),
#curDay int,
#prvDay int,
#shiftID int;
SELECT TOP 1
#shiftCalendarID = ID,
#curDay = DATEDIFF( dd, BeginDate, #dateTime ) % PeriodInDays + 1,
#prvDay = ( #curDay + PeriodInDays - 2 ) % PeriodInDays + 1
FROM ShiftCalendar
WHERE ID = #shiftCalendarID
OR ( #shiftCalendarID IS NULL
AND Name = 'Factory'
AND BeginDate <= #dateTime )
ORDER BY BeginDate DESC;
SELECT #shiftID = ID
FROM Shift
WHERE ShiftCalendarID = #shiftCalendarID
AND ( ( FromDay = #curDay AND FromTimeOfDay <= #time AND TillTimeOfDay > #time )
OR ( FromDay = #curDay AND FromTimeOfDay >= TillTimeOfDay AND FromTimeOfDay <= #time )
OR ( FromDay = #prvDay AND FromTimeOfDay >= TillTimeOfDay AND TillTimeOfDay > #time )
);
RETURN #shiftID;
END
--GO
I had help from a user writing this and was able to get this function written in snowflake and seems to be working properly. here it is below
--Function 1 -- Snowflake syntax, currently working
CREATE OR REPLACE FUNCTION DB_BI_DEV.RAW_CPMS_AAR.cfn_GetShiftIDFromDateTime (dateTime TIMESTAMP_NTZ(9), shiftCalendarID int)
RETURNS table (shiftID int)
AS
$$
WITH T0 (ShiftCalendarID, CurDay, PrvDay)
AS (
SELECT TOP 1
ID AS ShiftCalendarID,
DATEDIFF( day, BeginDate, dateTime ) % PeriodInDays + 1 AS CurDay,
( CurDay + PeriodInDays - 2 ) % PeriodInDays + 1 AS PrvDay
FROM RAW_CPMS_AAR.ShiftCalendar
WHERE ID = shiftCalendarID
OR ( shiftCalendarID IS NULL
AND Name = 'Factory'
AND BeginDate <= dateTime )
ORDER BY BeginDate DESC
),
T1 (TimeValue)
AS (
SELECT TIME_FROM_PARTS(
EXTRACT(HOUR FROM dateTime),
EXTRACT(MINUTE FROM dateTime),
EXTRACT(SECOND FROM dateTime))
)
SELECT ID as shiftID
FROM RAW_CPMS_AAR.Shift, T0, T1
WHERE Shift.ShiftCalendarID = T0.ShiftCalendarID
AND ( ( FromDay = T0.CurDay AND FromTimeOfDay <= T1.TimeValue AND TillTimeOfDay > T1.TimeValue )
OR ( FromDay = T0.CurDay AND FromTimeOfDay >= TillTimeOfDay AND FromTimeOfDay <= T1.TimeValue )
OR ( FromDay = T0.PrvDay AND FromTimeOfDay >= TillTimeOfDay AND TillTimeOfDay > T1.TimeValue )
)
$$
;
here is function 2:
--Function 2: Straight from SQL server
ALTER FUNCTION [dbo].[cfn_GetEquipmentShiftCalendarID] ( #equipmentID int, #date datetime )
RETURNS int
AS
BEGIN
IF #date IS NULL SET #date = GETDATE();
DECLARE
#shiftCalendarID int,
#endDate date;
WITH cte ( ID, ParentEquipmentID, ShiftCalendarEntityNumber ) AS (
SELECT ID, ParentEquipmentID, ShiftCalendarEntityNumber
FROM Equipment
WHERE ID = #equipmentID
UNION ALL
SELECT p.ID, p.ParentEquipmentID, p.ShiftCalendarEntityNumber
FROM cte
INNER JOIN Equipment p ON p.ID = cte.ParentEquipmentID AND cte.ShiftCalendarEntityNumber IS NULL
)
SELECT TOP 1 #shiftCalendarID = sc.ID, #endDate = sc.EndDate
FROM cte
INNER JOIN ShiftCalendar sc ON sc.EntityNumber = cte.ShiftCalendarEntityNumber
WHERE sc.BeginDate <= #date
ORDER BY
CASE WHEN EndDate IS NULL OR EndDate > #date THEN 1 ELSE 2 END, -- Prio on date range
sc.BeginDate DESC;
IF #shiftCalendarID IS NULL
BEGIN
-- Default to the last created calendar we find that started before the given time
SELECT TOP 1 #shiftCalendarID = ID
FROM ShiftCalendar
WHERE BeginDate < #date
ORDER BY BeginDate DESC;
END;
RETURN #shiftCalendarID; -- CASE WHEN #endDate IS NULL OR #endDate > #date THEN #shiftCalendarID END; -- Return NULL when no matching date range found?
END
GO
This one I was able to rewrite in snowflake but the if statement isnt working. I am not sure if snowflake function can use an if statement.
ALTER FUNCTION [dbo].[cfn_GetShiftIDFromDateTime] (
#dateTime datetime,
#shiftCalendarID int
)
RETURNS int
AS
BEGIN
DECLARE
#time time = CONVERT( time, #dateTime ),
#curDay int,
#prvDay int,
#shiftID int;
SELECT TOP 1
#shiftCalendarID = ID,
#curDay = DATEDIFF( dd, BeginDate, #dateTime ) % PeriodInDays + 1,
#prvDay = ( #curDay + PeriodInDays - 2 ) % PeriodInDays + 1
FROM ShiftCalendar
WHERE ID = #shiftCalendarID
OR ( #shiftCalendarID IS NULL
AND Name = 'Factory'
AND BeginDate <= #dateTime )
ORDER BY BeginDate DESC;
SELECT #shiftID = ID
FROM Shift
WHERE ShiftCalendarID = #shiftCalendarID
AND ( ( FromDay = #curDay AND FromTimeOfDay <= #time AND TillTimeOfDay > #time )
OR ( FromDay = #curDay AND FromTimeOfDay >= TillTimeOfDay AND FromTimeOfDay <= #time )
OR ( FromDay = #prvDay AND FromTimeOfDay >= TillTimeOfDay AND TillTimeOfDay > #time )
);
RETURN #shiftID;
END
--GO
so how are these functions used? i have a view which i was able to recreate in snowflake, but is missing the part that calls the function.
ALTER VIEW [proj].[pvw_PowerBI_ActualUnits]
SELECT
e.Name AS ProductionUnit,
temp.DateTime AS DateTime,
s.Reference AS Shift,
CONVERT(TIME, temp.DateTime) AS Time,
CONVERT(DATE, temp.DateTime - ISNULL((SELECT CAST(MIN(s_first.FromTimeOfDay) AS DateTime) FROM [Shift] s_first WHERE s_first.FromDay = s.FromDay AND s_first.ShiftCalendarID = s.ShiftCalendarID), CAST('6:00' AS DateTime))) AS ProductionDate,
'Actual Units' AS ScrapReason,
temp.ScrapQuantity AS ScrapQuantity,
'Auto Registered' AS RegistrationType,
s.ID
FROM
(SELECT
vl.EquipmentID AS ProductionUnit,
DATEADD(MINUTE, 30 * (DATEPART(MINUTE, vl.BeginTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, 0, vl.BeginTime), 0)) AS DateTime,
SUM(vl.Quantity) AS ScrapQuantity
FROM oee.ValueLog vl WITH (NOLOCK)
INNER JOIN KPIInstance ki ON ki.ID = vl.KPIInstanceID AND ki.KPIDefinitionID LIKE 'COUNT-OUT:%'
GROUP BY DATEADD(MINUTE, 30 * (DATEPART(MINUTE, vl.BeginTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, 0, vl.BeginTime), 0)), vl.EquipmentID) temp
INNER JOIN Equipment e ON e.ID = temp.ProductionUnit
INNER JOIN Shift s ON s.ID = dbo.cfn_GetShiftIDFromDateTime(temp.DateTime, dbo.cfn_GetEquipmentShiftCalendarID(temp.ProductionUnit, temp.DateTime)) -- here is where the functions are called
i was able to rewrite this in snowflake for the most part minus calling the function.
SELECT
e.Name AS ProductionUnit,
temp.DateTime AS DateTime,
s.Reference AS Shift,
temp.DateTime::TIME AS Time,
--CONVERT(DATE, temp.DateTime - ISNULL((SELECT CAST(MIN(s_first.FromTimeOfDay) AS DateTime) FROM [Shift] s_first WHERE s_first.FromDay = s.FromDay AND s_first.ShiftCalendarID = s.ShiftCalendarID), CAST('6:00' AS DateTime))) AS ProductionDate,
IFNULL(dateadd(HOUR, - (HOUR(SELECT MIN(s_first.FromTimeOfDay)
FROM RAW_CPMS_AAR.Shift s_first WHERE s_first.FromDay = s.FromDay AND s_first.ShiftCalendarID = s.ShiftCalendarID)), temp.DateTime), (dateadd(HOUR, - 6, temp.DateTime))) AS ProductionDate ,
'Actual Units' AS ScrapReason,
temp.ScrapQuantity AS ScrapQuantity,
'Auto Registered' AS RegistrationType
FROM
(SELECT
vl.EquipmentID AS ProductionUnit,
DATEADD(MIN, 30 * (DATE_PART(MINUTE, vl.BeginTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, '0', vl.BeginTime), '0')) AS DateTime,
SUM(vl.Quantity) AS ScrapQuantity
FROM RAW_CPMS_AAR.ValueLog vl
INNER JOIN KPIInstance ki ON ki.ID = vl.KPIInstanceID AND ki.KPIDefinitionID LIKE 'COUNT-OUT:%'
GROUP BY DATEADD(MIN, 30 * (DATE_PART(MINUTE, vl.BeginTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, '0', vl.BeginTime), '0')), vl.EquipmentID) as temp, shiftcalendar_cte, RAW_CPMS_AAR.Equipment e, RAW_CPMS_AAR.Shift s
WHERE e.ID = temp.ProductionUnit
Now i dont know if there is a better way to do this, maybe a cte is better. i know functions are not resource friendly, i'm simply trying to recreate this. open to any ideas or help.
ok, some small translations:
DATEADD(HOUR, DATEDIFF(HOUR, 0, vl.BeginTime), 0)
is truncating to the hour, so is the same as
date_trunc('HOUR', vl.BeginTime)
that dateadd thus is:
select column1
,date_trunc('hour', column1) as t_hour
,truncate(minute(column1)/30)*30
,timeadd('minute', truncate(minute(column1)/30)*30, date_trunc('hour', column1)) as datetime
from values
('2022-11-14 13:26:01'::timestamp_ntz),
('2022-11-14 12:34:01'::timestamp_ntz);
COLUMN1
T_HOUR
TRUNCATE(MINUTE(COLUMN1)/30)*30
DATETIME
2022-11-14 13:26:01.000
2022-11-14 13:00:00.000
0
2022-11-14 13:00:00.000
2022-11-14 12:34:01.000
2022-11-14 12:00:00.000
30
2022-11-14 12:30:00.000
So moving that sub-select that you alias as temp into a CTE, and get that "working"
WITH table_oee_valuelog(equipmentid, begintime, quantity, kpiinstanceid) as (
select * from values
(1, '2022-11-14 13:26:01'::timestamp_ntz, 10, 100),
(1, '2022-11-14 13:26:01'::timestamp_ntz, 11, 100),
(1, '2022-11-14 13:34:01'::timestamp_ntz, 12, 100)
), table_kpiinstance(id, kpidefinitionid) as (
select * from values
(100, 'COUNT-OUT:extra stuff')
)--, temp_sub_select as (
SELECT
vl.equipmentid as productionunit,
timeadd('minute', truncate(minute(vl.BeginTime)/30)*30, date_trunc('hour', vl.BeginTime)) as datetime,
SUM(vl.quantity) AS scrapquantity
FROM table_oee_valuelog as vl
INNER JOIN table_kpiinstance as ki
ON ki.ID = vl.KPIInstanceID
AND ki.KPIDefinitionID LIKE 'COUNT-OUT:%'
GROUP BY 1,2
;)
PRODUCTIONUNIT
DATETIME
SCRAPQUANTITY
1
2022-11-14 13:00:00.000
21
1
2022-11-14 13:30:00.000
12
implementing cfn_GetEquipmentShiftCalendarID
so if we extend our table data a bit more we can take a first crack at cfn_GetEquipmentShiftCalendarID like:
WITH table_oee_valuelog(equipmentid, begintime, quantity, kpiinstanceid) as (
select * from values
(1, '2022-11-14 13:26:01'::timestamp_ntz, 10, 100),
(1, '2022-11-14 13:26:01'::timestamp_ntz, 11, 100),
(1, '2022-11-14 13:34:01'::timestamp_ntz, 12, 100)
), table_kpiinstance(id, kpidefinitionid) as (
select * from values
(100, 'COUNT-OUT:extra stuff')
), table_equipment(id, name, parentequipmentid, shiftcalendarentitynumber) as (
select * from values
(1,'equipment one', 2, null),
(2,'equipment two', null, 80),
(3,'equipment three', 4, 81),
(4,'equipment four', null, 82)
), table_shift(id, shiftcalendarid, reference) as (
select * from values
(1001, 9001, 'a')
), table_shiftcalendar(id, entitynumber, begindate, enddate) as (
select * from values
(699, 80, '2021-01-01'::date, '2021-12-31'::date),
(700, 80, '2022-01-01'::date, '2022-12-31'::date),
--(701, 81, '2022-02-01'::date, '2022-11-30'::date),
(702, 82, '2022-10-01'::date, '2022-11-15'::date)
), cte_GetEquipmentShiftCalendarID/*(id, shiftCalendarID)*/ as (
with recursive rec_cte (id, parentequipmentid, shiftcalendarentitynumber) as (
select
ID,
ParentEquipmentID,
ShiftCalendarEntityNumber
FROM table_equipment
UNION ALL
SELECT
r.ID,
p.ParentEquipmentID,
p.ShiftCalendarEntityNumber
FROM rec_cte as r
INNER JOIN table_equipment p
ON p.ID = r.ParentEquipmentID
AND r.ShiftCalendarEntityNumber IS NULL
)
select * from rec_cte as c
left join table_shiftcalendar as sc
on sc.entitynumber = c.ShiftCalendarEntityNumber
where shiftcalendarentitynumber is not null
qualify row_number() over (partition by c.id order by sc.begindate desc ) = 1
)
select * from cte_GetEquipmentShiftCalendarID;
This is missing the #date based filters and the catch all, as to product the "latest" all bit of equipment, cannot be done yet.
ID
PARENTEQUIPMENTID
SHIFTCALENDARENTITYNUMBER
ID_2
ENTITYNUMBER
BEGINDATE
ENDDATE
1
80
700
80
2022-01-01
2022-12-31
2
80
700
80
2022-01-01
2022-12-31
3
4
81
4
82
702
82
2022-10-01
2022-11-15
so we need to weave this current data, with the temp table, how convenient we made it a CTE already...
so the next partial step is:
WITH table_oee_valuelog(equipmentid, begintime, quantity, kpiinstanceid) as (
select * from values
(1, '2022-11-14 13:26:01'::timestamp_ntz, 10, 100),
(1, '2022-11-14 13:26:01'::timestamp_ntz, 11, 100),
(1, '2022-11-14 13:34:01'::timestamp_ntz, 12, 100),
(2, '2022-11-14 13:34:01'::timestamp_ntz, 20, 100),
(3, '2022-11-14 13:34:01'::timestamp_ntz, 30, 100),
(4, '2022-11-14 13:34:01'::timestamp_ntz, 44, 100)
), table_kpiinstance(id, kpidefinitionid) as (
select * from values
(100, 'COUNT-OUT:extra stuff')
), table_equipment(id, name, parentequipmentid, shiftcalendarentitynumber) as (
select * from values
(1,'equipment one', 2, null),
(2,'equipment two', null, 80),
(3,'equipment three', 4, 81),
(4,'equipment four', null, 82)
), table_shift(id, shiftcalendarid, reference) as (
select * from values
(1001, 9001, 'a')
), table_shiftcalendar(id, entitynumber, begindate, enddate) as (
select * from values
(699, 80, '2021-01-01'::date, '2021-12-31'::date),
(700, 80, '2022-01-01'::date, '2022-12-31'::date),
(701, 80, '2023-01-01'::date, '2023-12-31'::date),
--(701, 81, '2022-02-01'::date, '2022-11-30'::date),
(702, 82, '2022-10-01'::date, '2022-11-15'::date)
), temp_sub_select as (
SELECT
vl.equipmentid as productionunit,
timeadd('minute', truncate(minute(vl.BeginTime)/30)*30, date_trunc('hour', vl.BeginTime)) as datetime,
SUM(vl.quantity) AS scrapquantity
FROM table_oee_valuelog as vl
INNER JOIN table_kpiinstance as ki
ON ki.ID = vl.KPIInstanceID
AND ki.KPIDefinitionID LIKE 'COUNT-OUT:%'
GROUP BY 1,2
), cte_GetEquipmentShiftCalendarID_part_a/*(id, shiftCalendarID)*/ as (
with recursive rec_cte (id, parentequipmentid, shiftcalendarentitynumber) as (
select
ID,
ParentEquipmentID,
ShiftCalendarEntityNumber
FROM table_equipment
UNION ALL
SELECT
r.ID,
p.ParentEquipmentID,
p.ShiftCalendarEntityNumber
FROM rec_cte as r
INNER JOIN table_equipment p
ON p.ID = r.ParentEquipmentID
AND r.ShiftCalendarEntityNumber IS NULL
)
select
c.id,
sc.id as shiftCalendarID,
sc.begindate, sc.enddate
from rec_cte as c
left join table_shiftcalendar as sc
on sc.entitynumber = c.ShiftCalendarEntityNumber
where shiftcalendarentitynumber is not null
)--, last_calendar_per_equipment as (
select *
,iff(c.enddate is null or c.enddate > t.datetime, 1, 2) as order_a
,row_number() over (partition by t.productionunit, t.datetime order by order_a, c.begindate desc) as rn
from temp_sub_select as t
left join cte_GetEquipmentShiftCalendarID_part_a as c
on t.productionunit = c.id
and c.begindate <= t.datetime
;)
this gives:
PRODUCTIONUNIT
DATETIME
SCRAPQUANTITY
ID
SHIFTCALENDARID
BEGINDATE
ENDDATE
ORDER_A
RN
1
2022-11-14 13:00:00.000
21
1
700
2022-01-01
2022-12-31
1
1
1
2022-11-14 13:00:00.000
21
1
699
2021-01-01
2021-12-31
2
2
1
2022-11-14 13:30:00.000
12
1
700
2022-01-01
2022-12-31
1
1
1
2022-11-14 13:30:00.000
12
1
699
2021-01-01
2021-12-31
2
2
2
2022-11-14 13:30:00.000
20
2
700
2022-01-01
2022-12-31
1
1
2
2022-11-14 13:30:00.000
20
2
699
2021-01-01
2021-12-31
2
2
3
2022-11-14 13:30:00.000
30
1
1
4
2022-11-14 13:30:00.000
44
4
702
2022-10-01
2022-11-15
1
1
last step of this function can be handled with this CTE which we can join to the prior results, and take if the prior results are null.
select
t.datetime,
sc.id
from (
select distinct datetime
from temp_sub_select
) as t
join table_shiftcalendar as sc
on sc.begindate <= t.datetime
qualify row_number() over (partition by t.datetime order by sc.begindate desc) = 1
weave those together and a little data change:
WITH table_oee_valuelog(equipmentid, begintime, quantity, kpiinstanceid) as (
select * from values
(1, '2022-11-14 13:26:01'::timestamp_ntz, 10, 100),
(1, '2022-11-14 13:26:01'::timestamp_ntz, 11, 100),
(1, '2022-11-14 13:34:01'::timestamp_ntz, 12, 100),
(2, '2022-11-14 13:34:01'::timestamp_ntz, 20, 100),
(3, '2022-11-14 13:34:01'::timestamp_ntz, 30, 100),
(4, '2022-11-14 13:34:01'::timestamp_ntz, 44, 100)
), table_kpiinstance(id, kpidefinitionid) as (
select * from values
(100, 'COUNT-OUT:extra stuff')
), table_equipment(id, name, parentequipmentid, shiftcalendarentitynumber) as (
select * from values
(1,'equipment one', 2, null),
(2,'equipment two', null, 80),
(3,'equipment three', 4, 81),
(4,'equipment four', null, 82)
), table_shift(id, shiftcalendarid, reference) as (
select * from values
(1001, 9001, 'a')
), table_shiftcalendar(id, entitynumber, begindate, enddate) as (
select * from values
(699, 80, '2021-01-01'::date, '2021-12-31'::date),
(700, 80, '2022-01-01'::date, '2022-12-31'::date),
(701, 80, '2023-01-01'::date, '2023-12-31'::date),
--(701, 81, '2022-02-01'::date, '2022-11-30'::date),
(702, 82, '2022-10-01'::date, '2022-11-15'::date),
(703, 89, '2022-11-01'::date, '2022-11-15'::date)
), temp_sub_select as (
SELECT
vl.equipmentid as productionunit,
timeadd('minute', truncate(minute(vl.BeginTime)/30)*30, date_trunc('hour', vl.BeginTime)) as datetime,
SUM(vl.quantity) AS scrapquantity
FROM table_oee_valuelog as vl
INNER JOIN table_kpiinstance as ki
ON ki.ID = vl.KPIInstanceID
AND ki.KPIDefinitionID LIKE 'COUNT-OUT:%'
GROUP BY 1,2
), cte_GetEquipmentShiftCalendarID_part_a/*(id, shiftCalendarID)*/ as (
with recursive rec_cte (id, parentequipmentid, shiftcalendarentitynumber) as (
select
ID,
ParentEquipmentID,
ShiftCalendarEntityNumber
FROM table_equipment
UNION ALL
SELECT
r.ID,
p.ParentEquipmentID,
p.ShiftCalendarEntityNumber
FROM rec_cte as r
INNER JOIN table_equipment p
ON p.ID = r.ParentEquipmentID
AND r.ShiftCalendarEntityNumber IS NULL
)
select
c.id,
sc.id as shiftCalendarID,
sc.begindate, sc.enddate
from rec_cte as c
left join table_shiftcalendar as sc
on sc.entitynumber = c.ShiftCalendarEntityNumber
where shiftcalendarentitynumber is not null
), cte_GetEquipmentShiftCalendarID_part_b as (
select t.productionunit,
t.org_datetime,
t.datetime,
c.shiftCalendarID
from (
select
productionunit,
datetime as org_datetime,
nvl(datetime, CURRENT_DATE) as datetime /* handle the null case from the T-SQL */
from temp_sub_select
) as t
left join cte_GetEquipmentShiftCalendarID_part_a as c
on t.productionunit = c.id
and c.begindate <= t.datetime
qualify row_number() over (partition by t.productionunit, t.datetime
order by iff(c.enddate is null or c.enddate > t.datetime, 1, 2), c.begindate desc) = 1
), max_shiftCalendar_per_datetime as (
select
t.datetime,
sc.id
from (
select distinct nvl(datetime, CURRENT_DATE) as datetime
from temp_sub_select
) as t
join table_shiftcalendar as sc
on sc.begindate <= t.datetime
qualify row_number() over (partition by t.datetime order by sc.begindate desc) = 1
)--, last_calendar_per_equipment as (
select
a.productionunit
,a.org_datetime
,a.shiftCalendarID, b.id
,nvl(a.shiftCalendarID, b.id) as shiftCalendarID
from cte_GetEquipmentShiftCalendarID_part_b as a
join max_shiftCalendar_per_datetime as b
on a.datetime = b.datetime
;)
gives:
PRODUCTIONUNIT
ORG_DATETIME
SHIFTCALENDARID
ID
SHIFTCALENDARID_2
1
2022-11-14 13:00:00.000
700
703
700
1
2022-11-14 13:30:00.000
700
703
700
2
2022-11-14 13:30:00.000
700
703
700
3
2022-11-14 13:30:00.000
703
703
4
2022-11-14 13:30:00.000
702
703
702
Mostly Complete answer:
So I striped ProductionDate and the two fixed string from my answer but:
--CREATE VIEW proj.pvw_PowerBI_ActualUnits
WITH table_oee_valuelog(equipmentid, begintime, quantity, kpiinstanceid) as (
select * from values
(1, '2022-11-14 13:26:01'::timestamp_ntz, 10, 100),
(1, '2022-11-14 13:26:01'::timestamp_ntz, 11, 100),
(1, '2022-11-14 13:34:01'::timestamp_ntz, 12, 100),
(2, '2022-11-14 13:34:01'::timestamp_ntz, 20, 100),
(3, '2022-11-14 13:34:01'::timestamp_ntz, 30, 100),
(4, '2022-11-14 13:34:01'::timestamp_ntz, 44, 100)
), table_kpiinstance(id, kpidefinitionid) as (
select * from values
(100, 'COUNT-OUT:extra stuff')
), table_equipment(id, name, parentequipmentid, shiftcalendarentitynumber) as (
select * from values
(1,'equipment one', 2, null),
(2,'equipment two', null, 80),
(3,'equipment three', 4, 81),
(4,'equipment four', null, 82)
), table_shift(id, shiftcalendarid, reference, FromDay, FromTimeOfDay, TillTimeOfDay) as (
select * from values
(1001, 700, 'a', 8, '06:00'::time,'18:00'::time),
(1001, 702, 'a', 5, '06:00'::time,'18:00'::time),
(1001, 703, 'a', 4, '06:00'::time,'18:00'::time)
), table_shiftcalendar(id, entitynumber, begindate, enddate, name, PeriodInDays) as (
select * from values
(699, 80, '2021-01-01'::date, '2021-12-31'::date, 'Factory', 10),
(700, 80, '2022-01-01'::date, '2022-12-31'::date, 'Factory', 10),
(701, 80, '2023-01-01'::date, '2023-12-31'::date, 'Factory', 10),
--(701, 81, '2022-02-01'::date, '2022-11-30'::date, 'Factory', 10),
(702, 82, '2022-10-01'::date, '2022-11-15'::date, 'Factory', 10),
(703, 89, '2022-11-01'::date, '2022-11-15'::date, 'Factory', 10)
), temp_sub_select as (
SELECT
vl.equipmentid as productionunit,
timeadd('minute', truncate(minute(vl.BeginTime)/30)*30, date_trunc('hour', vl.BeginTime)) as datetime,
SUM(vl.quantity) AS scrapquantity
FROM table_oee_valuelog as vl
INNER JOIN table_kpiinstance as ki
ON ki.ID = vl.KPIInstanceID
AND ki.KPIDefinitionID LIKE 'COUNT-OUT:%'
GROUP BY 1,2
), cte_GetEquipmentShiftCalendarID_part_a as (
with recursive rec_cte (id, parentequipmentid, shiftcalendarentitynumber) as (
select
ID,
ParentEquipmentID,
ShiftCalendarEntityNumber
FROM table_equipment
UNION ALL
SELECT
r.ID,
p.ParentEquipmentID,
p.ShiftCalendarEntityNumber
FROM rec_cte as r
INNER JOIN table_equipment p
ON p.ID = r.ParentEquipmentID
AND r.ShiftCalendarEntityNumber IS NULL
)
select
c.id,
sc.id as shiftCalendarID,
sc.begindate, sc.enddate
from rec_cte as c
left join table_shiftcalendar as sc
on sc.entitynumber = c.ShiftCalendarEntityNumber
where shiftcalendarentitynumber is not null
), cte_GetEquipmentShiftCalendarID_part_b as (
select t.productionunit,
t.org_datetime,
t.datetime,
c.shiftCalendarID
from (
select
productionunit,
datetime as org_datetime,
nvl(datetime, CURRENT_DATE) as datetime /* handle the null case from the T-SQL */
from temp_sub_select
) as t
left join cte_GetEquipmentShiftCalendarID_part_a as c
on t.productionunit = c.id
and c.begindate <= t.datetime
qualify row_number() over (partition by t.productionunit, t.datetime
order by iff(c.enddate is null or c.enddate > t.datetime, 1, 2), c.begindate desc) = 1
), max_shiftCalendar_per_datetime as (
select
t.datetime,
sc.id
from (
select distinct nvl(datetime, CURRENT_DATE) as datetime
from temp_sub_select
) as t
join table_shiftcalendar as sc
on sc.begindate <= t.datetime
qualify row_number() over (partition by t.datetime order by sc.begindate desc) = 1
), last_calendar_per_equipment as (
select
a.productionunit
,a.org_datetime
,nvl(a.shiftCalendarID, b.id) as shiftCalendarID
from cte_GetEquipmentShiftCalendarID_part_b as a
join max_shiftCalendar_per_datetime as b
on a.datetime = b.datetime
), cfn_GetShiftIDFromDateTime as (
with t0 as (
select
x.productionunit
,x.org_datetime
,x.org_datetime::time as org_time
,x.ShiftCalendarID
,DATEDIFF( day, BeginDate, x.org_datetime ) % PeriodInDays + 1 AS CurDay
,( CurDay + PeriodInDays - 2 ) % PeriodInDays + 1 AS PrvDay
from last_calendar_per_equipment as x
join table_shiftcalendar as sc
where sc.id = x.shiftCalendarID
OR ( x.shiftCalendarID IS NULL
AND sc.Name = 'Factory'
AND sc.BeginDate <= x.org_datetime )
QUALIFY row_number() over (partition by x.productionunit, x.org_datetime order by sc.begindate desc) = 1
)
SELECT
s.id
,s.reference
,productionunit
,org_datetime
,s.ShiftCalendarID
,s.FromDay, s.FromTimeOfDay, s.TillTimeOfDay, T0.CurDay, t0.org_time
FROM table_shift as s, T0
WHERE s.ShiftCalendarID = T0.ShiftCalendarID
AND ( ( s.FromDay = T0.CurDay AND s.FromTimeOfDay <= t0.org_time AND s.TillTimeOfDay > t0.org_time )
OR ( s.FromDay = T0.CurDay AND s.FromTimeOfDay >= s.TillTimeOfDay AND s.FromTimeOfDay <= t0.org_time )
OR ( s.FromDay = T0.PrvDay AND s.FromTimeOfDay >= s.TillTimeOfDay AND s.TillTimeOfDay > t0.org_time )
)
)
SELECT
e.name AS productionunit,
temp.datetime AS datetime,
s.reference AS shift,
temp.DateTime::time AS Time,
temp.ScrapQuantity AS ScrapQuantity,
s.ID
FROM temp_sub_select as temp
INNER JOIN table_equipment e
ON e.ID = temp.ProductionUnit
INNER JOIN cfn_GetShiftIDFromDateTime s
ON s.productionunit = temp.ProductionUnit
and temp.datetime = s.org_datetime
as far as I can follow, does what your functions do, and unrolls the correlated query, as that would never work in Snowflake.
PRODUCTIONUNIT
DATETIME
SHIFT
TIME
SCRAPQUANTITY
ID
equipment one
2022-11-14 13:00:00.000
a
13:00:00
21
1001
equipment one
2022-11-14 13:30:00.000
a
13:30:00
12
1001
equipment two
2022-11-14 13:30:00.000
a
13:30:00
20
1001
equipment three
2022-11-14 13:30:00.000
a
13:30:00
30
1001
equipment four
2022-11-14 13:30:00.000
a
13:30:00
44
1001
Not so bad for five hours work...

Count vowels and consonants in an array

I am trying to write a function which will return number of vowels
and consonants. Using the IF statement function will successfully
compile, however when I call it in the select it shows the message :
"Conversion failed when converting the varchar value 'MAMAMIA' to
data type int."`
I tried with the CASE statement, but there are too many syntax
errors and i think it is not the best method of solving the problem
using CASE ...
CREATE FUNCTION VOW_CONS(#ARRAY VARCHAR(20))
RETURNS INT
BEGIN
DECLARE #COUNTT INT;
DECLARE #COUNTT1 INT;
SET #COUNTT=0;
SET #COUNTT1=0;
WHILE (#ARRAY!=0)
BEGIN
IF(#ARRAY LIKE '[aeiouAEIOU]%')
SET #COUNTT=#COUNTT+1
ELSE SET #COUNTT1=#COUNTT1+1
/*
DECLARE #C INT;
SET #C=(CASE #SIR WHEN 'A' THEN #COUNTT=#COUNTT+1;
WHEN 'E' THEN #COUNTT=#COUNTT+1
WHEN 'I' THEN #COUNTT=#COUNTT+1
WHEN 'O' THEN #COUNTT=#COUNTT+1
WHEN 'U' THEN #COUNTT=#COUNTT+1
WHEN 'A' THEN #COUNTT=#COUNTT+1
WHEN ' ' THEN ' '
ELSE #COUNTT1=#COUNTT1+1
END)
*/
END
RETURN #COUNTT;
END
SELECT DBO.VOW_CONS('MAMAMIA')
Without knowing what version of SQL Server you are using, I am going to assume you are using the latest version, meaning you have access to TRANSLATE. Also I'm going to assume you do need access to both the number of vowels and consonants, so a table-value function seems the better method here. As such, you could do something like this:
CREATE FUNCTION dbo.CountVowelsAndConsonants (#String varchar(20))
RETURNS table
AS RETURN
SELECT DATALENGTH(#String) - DATALENGTH(REPLACE(TRANSLATE(#String,'aeiou','|||||'),'|','')) AS Vowels, --Pipe is a character that can't be in your string
DATALENGTH(#String) - DATALENGTH(REPLACE(TRANSLATE(#String,'bcdfghjklmnpqrstvwxyz','|||||||||||||||||||||'),'|','')) AS Consonants --Pipe is a character that can't be in your string
GO
And then you can use the function like so:
SELECT *
FROM (VALUES('MAMAMIA'),('Knowledge is power'))V(YourString)
CROSS APPLY dbo.CountVowelsAndConsonents(V.YourString);
Another option would be to split the string into its individual letters using a tally table, join that to a table of vowels/consonants and then get your counts.
Here is a working example, you'll have to update/change for your specific needs but should give you an idea on how it works.
DECLARE #string NVARCHAR(100)
SET #string = 'Knowledge is power';
--Here we build a table of all the letters setting a flag on which ones are vowels
DECLARE #VowelConsonants TABLE
(
[Letter] CHAR(1)
, [IsVowel] BIT
);
--We load it with the data
INSERT INTO #VowelConsonants (
[Letter]
, [IsVowel]
)
VALUES ( 'a', 1 ) , ( 'b', 0 ) , ( 'c', 0 ) , ( 'd', 0 ) , ( 'e', 1 ) , ( 'f', 0 ) , ( 'g', 0 ) , ( 'h', 0 ) , ( 'i', 1 ) , ( 'j', 0 ) , ( 'k', 0 ) , ( 'l', 0 ) , ( 'm', 0 ) , ( 'n', 0 ) , ( 'o', 1 ) , ( 'p', 0 ) , ( 'q', 0 ) , ( 'r', 0 ) , ( 's', 0 ) , ( 't', 0 ) , ( 'u', 1 ) , ( 'v', 0 ) , ( 'w', 0 ) , ( 'x', 0 ) , ( 'y', 0 ) , ( 'z', 0 );
--This tally table example gives 10,000 numbers
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
SELECT SUM( CASE WHEN [vc].[IsVowel] = 1 THEN 1
ELSE 0
END
) AS [VowelCount]
, SUM( CASE WHEN [vc].[IsVowel] = 0 THEN 1
ELSE 0
END
) AS [ConsonantCount]
FROM [cteTally] [t] --Select from tally cte
INNER JOIN #VowelConsonants [vc] --Join to VowelConsonants table on the letter.
ON LOWER([vc].[Letter]) = LOWER(SUBSTRING(#string, [t].[N], 1)) --Using the number from the tally table we can easily split out each letter using substring
WHERE [t].[N] <= LEN(#string);
Giving you results of:
VowelCount ConsonantCount
----------- --------------
6 10

MySQL - Calculate Revenue per employee per month

I am trying to calculate from my table "Revenue per employee"(how much money each employee generates for the company) per month.
My code So far:
SELECT
y.yr,
d.details,
d.labelname,
sum(case when month(app_date) = 1 then val else 0 end) month_01,
sum(case when month(app_date) = 2 then val else 0 end) month_02,
sum(case when month(app_date) = 3 then val else 0 end) month_03,
sum(case when month(app_date) = 4 then val else 0 end) month_04,
sum(case when month(app_date) = 5 then val else 0 end) month_05,
sum(case when month(app_date) = 6 then val else 0 end) month_06,
sum(case when month(app_date) = 7 then val else 0 end) month_07,
sum(case when month(app_date) = 8 then val else 0 end) month_08,
sum(case when month(app_date) = 9 then val else 0 end) month_09,
sum(case when month(app_date) = 10 then val else 0 end) month_10,
sum(case when month(app_date) = 11 then val else 0 end) month_11,
sum(case when month(app_date) = 12 then val else 0 end) month_12,
sum(case when month(app_date) > 0 then val else 0 end) total
from (
select 'a' dorder,'Peter' labelname,'1' details union all
select 'b' dorder,'John + Mary' labelname,'2' details union all
select 'c' dorder,'John' labelname,'3' details
) d cross join (
select distinct year(app_date) yr
from tblapp
) y
left join (
SELECT app_date, COALESCE(app_price, 0) val, '1' details from tblapp
INNER JOIN tblemployee ON tblemployee.emp_id = tblapp.emp_id
where tblemployee.emp_id=1
union all
SELECT app_date, COALESCE(app_price, 0) val, '2' details from tblapp
INNER JOIN tblemployee ON tblemployee.emp_id = tblapp.emp_id
INNER JOIN tblassistant ON tblassistant.ass_id = tblapp.ass_id
where tblemployee.emp_id=2 AND tblassistant.ass_id=1
union all
SELECT app_date, COALESCE(app_price, 0) val, '3' details from tblapp
INNER JOIN tblemployee ON tblemployee.emp_id = tblapp.emp_id
where tblemployee.emp_id=2
) t on year(t.app_date) = y.yr and t.details = d.details
group by y.yr, d.details
order by y.yr desc, d.dorder;
Code is working fine. Only problem is when i add a new employee or assistant, i have to edit the code and create manually the WHERE conditions(groups between employee and assistant)
CREATE TABLE `tblapp` (
`app_id` smallint(5) UNSIGNED NOT NULL,
`app_date` date DEFAULT NULL,
`app_price` double DEFAULT NULL,
`emp_id` smallint(5) UNSIGNED DEFAULT NULL,
`ass_id` smallint(5) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tblapp` (`app_id`, `app_date`, `app_price`, `emp_id`, `ass_id`) VALUES
(1, '2021-01-04', 100, 1, NULL),
(2, '2021-01-29', 100, 5, 1),
(3, '2021-02-20', 100, 2, 1),
(4, '2021-02-02', 100, 3, 2),
(5, '2021-03-19', 100, 2, NULL),
(6, '2021-04-24', 100, 4, 2),
(7, '2021-05-09', 100, 1, 1),
(8, '2021-07-04', 100, 2, 2),
(9, '2021-09-18', 100, 3, 1),
(10, '2021-10-12', 100, 5, NULL);
CREATE TABLE `tblemployee` (
`emp_id` smallint(5) UNSIGNED NOT NULL,
`emp_name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tblemployee` (`emp_id`, `emp_name`) VALUES
(1, 'Peter'),
(2, 'John'),
(3, 'Alex'),
(4, 'Stack'),
(5, 'Over'),
(6, 'Flow');
CREATE TABLE `tblassistant` (
`ass_id` smallint(5) UNSIGNED NOT NULL,
`ass_name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tblassistant` (`ass_id`, `ass_name`) VALUES
(1, 'Mary'),
(2, 'Andrew'),
(3, 'John'),
(4, 'Helen');
http://sqlfiddle.com/#!9/3fd588/3

SSRS subscription migration

I have several SSRS subscriptions built but my company just did a domain conversion and those subscriptions are all saved to my old domain login. This had led to a few questions:
1) Is there a way to move all those subscriptions to my new account?
2) Is it possible to setup the subscriptions to be viewable by multiple users?
3) Is it possible to setup the subscriptions to be editable by multiple users?
We are using SSRS 2012
I had to do this a few times at my last organization.
To answer your first question, I use the script below to update the subscription and report owners. I use SQL Command Mode to easily change to different servers. It is also necessary for the variables.
To turn on SQL Command Mode in SSMS, on the menu bar click on Query | SQLCMD Mode
Note: The NewUser must already exist in dbo.Users and you must have UPDATE permission on the dbo.ReportServer database to use this script.
/*------------------------------------------------------------------------------+
| Purpose: To Update the owner of deployed reports and subscriptions
| Note: SQLCmdMode Script
+--------------------------------------------------------------------------------
*/
:setvar _server "***YourServerNameHere***"
:setvar _database "ReportServer"
:connect $(_server)
USE [$(_database)];
GO
:SETVAR OldUser "DOMAIN\OldUserName"
:SETVAR NewUser "DOMAIN\NewUserName"
SET XACT_ABORT ON
BEGIN TRANSACTION
PRINT '====================================================================='
PRINT 'Update subscriptions...'
PRINT '====================================================================='
;WITH
new_owner
AS
(
SELECT [UserID], [UserName] FROM dbo.[Users] WHERE [UserName] = N'$(NewUser)'
)
,
subscription_source
AS
(
SELECT
s.[Report_OID]
, [OldOwner] = ou.[UserName]
, [OldOwnerID] = ou.[UserID]
, [NewOwner] = nu.[UserName]
, [NewOwnerID] = nu.[UserID]
FROM
dbo.[Subscriptions] AS s
INNER JOIN dbo.[Users] AS ou ON ou.[UserID] = s.[OwnerID]
, new_owner AS nu
WHERE
1=1
AND ou.[UserName] = N'$(OldUser)'
)
--SELECT * FROM subscription_source
MERGE dbo.Subscriptions AS T
USING subscription_source AS S ON T.[Report_OID] = S.[Report_OID]
WHEN MATCHED
THEN UPDATE SET
T.[OwnerID] = S.[NewOwnerID]
OUTPUT ##ServerName AS ServerName, db_name() AS DatabaseName, $action, inserted.*, deleted.*;
PRINT '====================================================================='
PRINT 'Update report created by...'
PRINT '====================================================================='
;WITH
new_owner
AS
(
SELECT [UserID], [UserName] FROM dbo.[Users] WHERE [UserName] = N'$(NewUser)'
)
,
report_list_source
AS
(
SELECT
c.[ItemID]
, c.[Name]
, [OldOwner] = ou.[UserName]
, [OldOwnerID] = ou.[UserID]
, [NewOwner] = nu.[UserName]
, [NewOwnerID] = nu.[UserID]
FROM
dbo.[Catalog] AS c
INNER JOIN dbo.[Users] AS ou ON ou.[UserID] = c.[CreatedById]
, new_owner AS nu
WHERE
1=1
AND ou.[UserName] = N'$(OldUser)'
AND c.[Type] = 2
)
--SELECT * FROM report_list_source
MERGE dbo.[Catalog] AS T
USING report_list_source AS S ON T.[ItemID] = S.[ItemID]
WHEN MATCHED
THEN UPDATE SET
T.[CreatedById] = S.[NewOwnerID]
OUTPUT ##ServerName AS ServerName, db_name() AS DatabaseName, $action, inserted.*, deleted.*;
PRINT '====================================================================='
PRINT 'Update report modified by...'
PRINT '====================================================================='
;WITH
new_owner
AS
(
SELECT [UserID], [UserName] FROM dbo.[Users] WHERE [UserName] = N'$(NewUser)'
)
,
report_list_source
AS
(
SELECT
c.[ItemID]
, c.[Name]
, [OldOwner] = ou.[UserName]
, [OldOwnerID] = ou.[UserID]
, [NewOwner] = nu.[UserName]
, [NewOwnerID] = nu.[UserID]
FROM
dbo.[Catalog] AS c
INNER JOIN dbo.[Users] AS ou ON ou.[UserID] = c.[ModifiedById]
, new_owner AS nu
WHERE
1=1
AND ou.[UserName] = N'$(OldUser)'
AND c.[Type] = 2
)
--SELECT * FROM report_list_source
MERGE dbo.[Catalog] AS T
USING report_list_source AS S ON T.[ItemID] = S.[ItemID]
WHEN MATCHED
THEN UPDATE SET
T.[ModifiedById] = S.[NewOwnerID]
OUTPUT ##ServerName AS ServerName, db_name() AS DatabaseName, $action, inserted.*, deleted.*;
PRINT '******* ROLLBACK TRANSACTION ******* ';
ROLLBACK TRANSACTION;
--PRINT '******* COMMIT TRANSACTION ******* ';
--COMMIT TRANSACTION;
PRINT '====================================================================='
PRINT 'Finished...'
PRINT '====================================================================='
To answer your second question, I wrote a report to view all the subscriptions. Below is the report SQL. Here is the rdl file if you just want to download that.
/*'------------------------------------------------------------------------------------------------------------------
| Purpose: Schedule Of Recurring Report Subscriptions
| Note: SQLCmdMode Script
'--------------------------------------------------------------------------------------------------------------------
DECLARE #all_value AS VARCHAR(100)
DECLARE #ReportFolder AS VARCHAR(100)
DECLARE #ReportName AS VARCHAR(100)
DECLARE #EmailLike AS VARCHAR(100)
DECLARE #ModifiedBy AS VARCHAR(50)
DECLARE #SubcriptionOwner AS VARCHAR(50)
DECLARE #SubscriptionStatus AS VARCHAR(1)
DECLARE #EventStatus AS VARCHAR(50)
DECLARE #Current AS VARCHAR(50)
DECLARE #LastSubscriptionDate AS DATETIME
SET #all_value = '<ALL>'
SET #ReportFolder = '<ALL>'
SET #ReportName = '<ALL>'
SET #EmailLike = NULL
SET #ModifiedBy = NULL
SET #SubcriptionOwner = NULL
SET #SubscriptionStatus = 'A' -- Y=Sent, N=Fail, A=All
SET #EventStatus = '<ALL>' -- status from ReportServer.dbo.ExecutionLog
SET #Current = '<ALL>'
SET #LastSubscriptionDate = NULL --getdate()-1
*/
;WITH
report_users
AS
(
SELECT [UserID], [UserName], [SimpleUserName] = UPPER(RIGHT([UserName],(LEN([UserName])-CHARINDEX('\',[UserName])))) FROM dbo.[Users]
)
,
report_catalog
AS
(
SELECT
c.[ItemID]
, c.[CreatedById]
, c.[ModifiedById]
, c.[Type]
, c.[Name]
, c.[Description]
, c.[Parameter]
, [ReportCreationDate] = CONVERT(DATETIME, CONVERT(VARCHAR(11), c.[CreationDate], 13))
, [ReportModifiedDate] = CONVERT(DATETIME, CONVERT(VARCHAR(11), c.[ModifiedDate], 13))
, [ReportFolder] =
CASE
WHEN c.[Path] = '/' + c.[Name] THEN ''
ELSE SUBSTRING(c.[Path], 2, Len(c.[Path])-Len(c.[Name])-2)
END
, [ReportPath] = c.[Path]
, [UrlPath] = 'http://' + Host_Name() + '/Reports/Pages/Folder.aspx?ItemPath=%2f'
, [ReportDefinition] = CONVERT(VARCHAR(MAX),CONVERT(VARBINARY(MAX), c.[Content]))
FROM
dbo.[Catalog] AS c
WHERE c.[Type] = 2
)
,
subscription_days
AS
(
SELECT tbl.* FROM (VALUES
( 'DaysOfMonth', 1, '1')
, ( 'DaysOfMonth', 2, '2')
, ( 'DaysOfMonth', 4, '3')
, ( 'DaysOfMonth', 8, '4')
, ( 'DaysOfMonth', 16, '5')
, ( 'DaysOfMonth', 32, '6')
, ( 'DaysOfMonth', 64, '7')
, ( 'DaysOfMonth', 128, '8')
, ( 'DaysOfMonth', 256, '9')
, ( 'DaysOfMonth', 512, '10')
, ( 'DaysOfMonth', 1024, '11')
, ( 'DaysOfMonth', 2048, '12')
, ( 'DaysOfMonth', 4096, '13')
, ( 'DaysOfMonth', 8192, '14')
, ( 'DaysOfMonth', 16384, '15')
, ( 'DaysOfMonth', 32768, '16')
, ( 'DaysOfMonth', 65536, '17')
, ( 'DaysOfMonth', 131072, '18')
, ( 'DaysOfMonth', 262144, '19')
, ( 'DaysOfMonth', 524288, '20')
, ( 'DaysOfMonth', 1048576, '21')
, ( 'DaysOfMonth', 2097152, '22')
, ( 'DaysOfMonth', 4194304, '23')
, ( 'DaysOfMonth', 8388608, '24')
, ( 'DaysOfMonth', 16777216, '25')
, ( 'DaysOfMonth', 33554432, '26')
, ( 'DaysOfMonth', 67108864, '27')
, ( 'DaysOfMonth', 134217728, '28')
, ( 'DaysOfMonth', 268435456, '29')
, ( 'DaysOfMonth', 536870912, '30')
, ( 'DaysOfMonth', 1073741824, '31')
, ( 'DaysOfMonth', 8193, '1st and 14th')
, ( 'DaysOfWeek', 1, 'Sun')
, ( 'DaysOfWeek', 2, 'Mon')
, ( 'DaysOfWeek', 4, 'Tues')
, ( 'DaysOfWeek', 8, 'Wed')
, ( 'DaysOfWeek', 16, 'Thurs')
, ( 'DaysOfWeek', 32, 'Fri')
, ( 'DaysOfWeek', 64, 'Sat')
, ( 'DaysOfWeek', 62, 'Mon - Fri')
, ( 'DaysOfWeek', 10, 'Mon - Wed')
, ( 'DaysOfWeek', 24, 'Wed - Thurs')
, ( 'DaysOfWeek', 120, 'Wed - Sat')
, ( 'DaysOfWeek', 126, 'Mon - Sat')
, ( 'DaysOfWeek', 127, 'Daily')
, ( 'DayOfWeek', 1, 'Sun')
, ( 'DayOfWeek', 127, 'Sun')
, ( 'DayOfWeek', 2, 'Mon')
, ( 'DayOfWeek', 10, 'Mon')
, ( 'DayOfWeek', 62, 'Mon')
, ( 'DayOfWeek', 126, 'Mon')
, ( 'DayOfWeek', 127, 'Mon')
, ( 'DayOfWeek', 4, 'Tue')
, ( 'DayOfWeek', 10, 'Tue')
, ( 'DayOfWeek', 62, 'Tue')
, ( 'DayOfWeek', 126, 'Tue')
, ( 'DayOfWeek', 127, 'Tue')
, ( 'DayOfWeek', 8, 'Wed')
, ( 'DayOfWeek', 10, 'Wed')
, ( 'DayOfWeek', 24, 'Wed')
, ( 'DayOfWeek', 62, 'Wed')
, ( 'DayOfWeek', 120, 'Wed')
, ( 'DayOfWeek', 126, 'Wed')
, ( 'DayOfWeek', 127, 'Wed')
, ( 'DayOfWeek', 16, 'Thr')
, ( 'DayOfWeek', 24, 'Thr')
, ( 'DayOfWeek', 62, 'Thr')
, ( 'DayOfWeek', 120, 'Thr')
, ( 'DayOfWeek', 126, 'Thr')
, ( 'DayOfWeek', 127, 'Thr')
, ( 'DayOfWeek', 32, 'Fri')
, ( 'DayOfWeek', 62, 'Fri')
, ( 'DayOfWeek', 120, 'Fri')
, ( 'DayOfWeek', 126, 'Fri')
, ( 'DayOfWeek', 127, 'Fri')
, ( 'DayOfWeek', 64, 'Sat')
, ( 'DayOfWeek', 120, 'Sat')
, ( 'DayOfWeek', 126, 'Sat')
, ( 'DayOfWeek', 127, 'Sat')
) tbl ([GroupName], [CodeNbr], [Label])
)
,
subscription_schedule
AS
(
SELECT
[ScheduleID]
, [SchDaySun] = Sun
, [SchDayMon] = Mon
, [SchDayTue] = Tue
, [SchDayWed] = Wed
, [SchDayThr] = Thr
, [SchDayFri] = Fri
, [SchDaySat] = Sat
, [ScheduleName]
, [ScheduleStartDate]
, [ScheduleEndDate]
, [Flags]
, [RecurrenceType]
, [State]
, [MinutesInterval]
, [DaysInterval]
, [WeeksInterval]
, [DaysOfWeek]
, [DaysOfMonth]
, [Month]
, [MonthlyWeek]
, [ScheduleDays]
FROM
(
SELECT
sc.[ScheduleID]
, sd.[CodeNbr]
, sd.[Label]
, [ScheduleName] = sc.[name]
, [ScheduleStartDate] = sc.[StartDate]
, [ScheduleEndDate] = sc.[EndDate]
, sc.[Flags]
, sc.[RecurrenceType]
, sc.[State]
, sc.[MinutesInterval]
, sc.[DaysInterval]
, sc.[WeeksInterval]
, sc.[DaysOfWeek]
, sc.[DaysOfMonth]
, sc.[Month]
, sc.[MonthlyWeek]
, [ScheduleDays] =
CASE
WHEN sc.[DaysOfMonth] IS NOT NULL THEN COALESCE(dom.[Label], '(' + CAST(sc.[DaysOfMonth] AS VARCHAR(20)) + ') NOT CODED')
WHEN sc.[DaysOfWeek] IS NOT NULL THEN COALESCE(dow.[Label], '(' + CAST(sc.[DaysOfWeek] AS VARCHAR(20)) + ') NOT CODED')
END
--, sc.[RecurrenceType]
FROM
dbo.[Schedule] sc
LEFT JOIN subscription_days sd ON sc.[DaysOfWeek] = sd.[CodeNbr] AND sd.[GroupName] = 'DayOfWeek'
LEFT JOIN subscription_days AS dom ON sc.[DaysOfMonth] = dom.[CodeNbr] AND dom.[GroupName] = 'DaysOfMonth'
LEFT JOIN subscription_days AS dow ON sc.DaysOfWeek = dow.CodeNbr AND dow.[GroupName] = 'DaysOfWeek'
) sch
PIVOT
(
COUNT(sch.[Label])
FOR sch.[Label]
IN ([Sun], [Mon], [Tue], [Wed], [Thr], [Fri], [Sat])
) AS pvt
)
,
report_subscription
AS
(
SELECT
s.[SubscriptionID]
, s.[Report_OID]
, [SubscriptionDescription] = s.[Description]
, s.[ExtensionSettings]
, s.[EventType]
, s.[OwnerID]
, s.[ModifiedByID]
, s.[ModifiedDate]
, [RunTime] = CONVERT(VARCHAR(5), s.[LastRunTime], 8)
, [LastRunDate] = CONVERT(VARCHAR(11),s.[LastRunTime],13)
, s.[LastRunTime]
, s.[DeliveryExtension]
, s.[MatchData]
, [SubscriptionLastStatus] = s.[LastStatus]
, [StatusFail] = CASE WHEN s.[LastStatus] LIKE '%Mail sent%' THEN 'N' ELSE 'Y' END
, [EmailSubject] = CASE CHARINDEX('<Name>SUBJECT</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>SUBJECT</Name><Value>') + CHARINDEX('<Name>SUBJECT</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>SUBJECT</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>SUBJECT</Name><Value>') + CHARINDEX('<Name>SUBJECT</Name><Value>', s.ExtensionSettings))) END
, [EmailTo] = SUBSTRING(s.ExtensionSettings, LEN('<Name>TO</Name><Value>') + CHARINDEX('<Name>TO</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>TO</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>TO</Name><Value>') + CHARINDEX('<Name>TO</Name><Value>', s.ExtensionSettings)))
, [EmailCc] = CASE CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>CC</Name><Value>') + CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>CC</Name><Value>') + CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings))) END
, [EmailBcc] = CASE CHARINDEX('<Name>BCC</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>BCC</Name><Value>') + CHARINDEX('<Name>BCC</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>BCC</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>BCC</Name><Value>') + CHARINDEX('<Name>BCC</Name><Value>', s.ExtensionSettings))) END
, [EmailComment] = CASE CHARINDEX('<Name>Comment</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>Comment</Name><Value>') + CHARINDEX('<Name>Comment</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>Comment</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>Comment</Name><Value>') + CHARINDEX('<Name>Comment</Name><Value>', s.ExtensionSettings))) END
, [EmailIncludeLink] = CASE CHARINDEX('<Name>IncludeLink</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>IncludeLink</Name><Value>') + CHARINDEX('<Name>IncludeLink</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>IncludeLink</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>IncludeLink</Name><Value>') + CHARINDEX('<Name>IncludeLink</Name><Value>', s.ExtensionSettings))) END
, [EmailRenderFormat] = CASE CHARINDEX('<Name>RenderFormat</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>RenderFormat</Name><Value>') + CHARINDEX('<Name>RenderFormat</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>RenderFormat</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>RenderFormat</Name><Value>') + CHARINDEX('<Name>RenderFormat</Name><Value>', s.ExtensionSettings))) END
, [EmailPriority] = CASE CHARINDEX('<Name>Priority</Name><Value>', s.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>Priority</Name><Value>') + CHARINDEX('<Name>Priority</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>Priority</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>Priority</Name><Value>') + CHARINDEX('<Name>Priority</Name><Value>', s.ExtensionSettings))) END
, sch.[MinutesInterval]
, sch.[DaysInterval]
, sch.[WeeksInterval]
, sch.[DaysOfWeek]
, sch.[DaysOfMonth]
, sch.[Month]
, sch.[MonthlyWeek]
--, [JobName] = sj.[name]
, sch.[ScheduleName]
, sch.[ScheduleDays]
, sch.[SchDaySun]
, sch.[SchDayMon]
, sch.[SchDayTue]
, sch.[SchDayWed]
, sch.[SchDayThr]
, sch.[SchDayFri]
, sch.[SchDaySat]
, sch.[ScheduleStartDate]
, sch.[ScheduleEndDate]
, sch.[Flags]
, sch.[RecurrenceType]
, sch.[State]
FROM
dbo.[Subscriptions] AS s
LEFT JOIN dbo.[Notifications] AS n ON n.[SubscriptionID] = s.[SubscriptionID] AND s.[Report_OID] = n.[ReportID]
LEFT JOIN dbo.[ReportSchedule] AS rs ON s.[SubscriptionID] = rs.[SubscriptionID]
--LEFT JOIN MSDB.dbo.[sysjobs] AS sj ON sj.[name] = CAST(rs.[ScheduleID] AS VARCHAR(255))
LEFT JOIN subscription_schedule AS sch ON rs.[ScheduleID] = sch.[ScheduleID]
WHERE
1=1
--AND sch.[RecurrenceType] IN(4,5) -- 1 = is one off, 4 = daily, 5 = monthly
--AND s.EventType = 'TimedSubscription'
)
SELECT
c.[Name]
, c.[Description]
, c.[Parameter]
, c.[ReportFolder]
, c.[ReportPath]
, [URL_ReportFolder] = c.[UrlPath] + c.[ReportFolder] + '&ViewMode=List'
, [URL_Report] = c.[UrlPath] + c.[ReportFolder] + '%2f' + c.Name
, [URL] = 'http://' + Host_Name() + '/Reports/Pages/SubscriptionProperties.aspx?ItemPath=' + c.ReportPath + '&IsDataDriven=False&SubscriptionID=' + CAST(s.SubscriptionID AS VARCHAR(80))
, [URL2] = 'http://' + Host_Name() + '/Reports/Pages/Report.aspx?ItemPath=' + c.[ReportPath] + '&SelectedTabId=SubscriptionsTab'
, [ReportCreatedBy] = urc.[SimpleUserName]
, c.[ReportCreationDate]
, [ReportModifiedBy] = urm.[SimpleUserName]
, c.[ReportModifiedDate]
, [SubscriptionOwner] = usc.[SimpleUserName]
, [SubscriptionModifiedBy] = usm.[SimpleUserName]
, [SubscriptionModifiedDate] = s.[ModifiedDate]
, s.[SubscriptionID]
, s.[SubscriptionDescription]
, s.[ExtensionSettings]
, s.[EventType]
, s.[EmailSubject]
, s.[EmailTo]
, s.[EmailCc]
, s.[EmailBcc]
, s.[EmailComment]
, s.[EmailIncludeLink]
, s.[EmailRenderFormat]
, s.[EmailPriority]
, s.[DeliveryExtension]
, s.[SubscriptionLastStatus]
, s.[StatusFail]
, s.[MatchData]
, s.[RunTime]
, s.[LastRunDate]
, s.[LastRunTime]
, s.[MinutesInterval]
, s.[DaysInterval]
, s.[WeeksInterval]
, s.[DaysOfWeek]
, s.[DaysOfMonth]
, s.[Month]
, s.[MonthlyWeek]
, [JobName] = NULL --, s.[JobName]
, s.[ScheduleName]
, s.[ScheduleDays]
, s.[SchDaySun]
, s.[SchDayMon]
, s.[SchDayTue]
, s.[SchDayWed]
, s.[SchDayThr]
, s.[SchDayFri]
, s.[SchDaySat]
, s.[ScheduleStartDate]
, s.[ScheduleEndDate]
, s.[Flags]
, s.[RecurrenceType]
, s.[State]
, [EventStatus] = el.[Status]
, [EventDateTime] = el.[TimeEnd]
FROM
report_catalog AS c
INNER JOIN report_subscription AS s ON s.[Report_OID] = c.[ItemID]
LEFT OUTER JOIN (SELECT b.[ReportID], b.[Status], b.[TimeEnd]
FROM dbo.[ExecutionLog] b
INNER JOIN (SELECT [ReportID], MAX([TimeEnd]) AS [TimeEnd]
FROM dbo.[ExecutionLog]
GROUP BY [ReportID]) a ON b.[ReportID] = a.[ReportID] AND b.[TimeEnd] = a.[TimeEnd]
)AS el ON el.[ReportID] = c.[ItemID]
LEFT OUTER JOIN report_users AS urc ON c.[CreatedById] = urc.[UserID]
LEFT OUTER JOIN report_users AS urm ON c.[ModifiedById] = urm.[UserID]
LEFT OUTER JOIN report_users AS usc ON s.[OwnerID] = usc.[UserID]
LEFT OUTER JOIN report_users AS usm ON s.[ModifiedByID] = usm.[UserID]
WHERE
1=1
AND c.[Type] = 2
AND (#all_value IN (#ReportFolder) OR c.[ReportFolder] IN(#ReportFolder))
AND (#all_value IN (#ReportFolder) OR CHARINDEX(#ReportFolder, c.[ReportPath]) > 0)
AND (#all_value IN(#ReportName) OR c.[Name] IN(#ReportName))
AND (#all_value IN(#EventStatus) OR el.[Status] IN(#EventStatus))
AND (#all_value IN(#Current) OR CASE WHEN s.[ScheduleEndDate] IS NULL THEN 'Current' WHEN s.[ScheduleEndDate] IS NOT NULL THEN 'Non Current' END = #Current)
AND (#all_value IN(#SubscriptionStatus) OR s.[SubscriptionLastStatus] LIKE '%' + #SubscriptionStatus + '%')
AND (s.[LastRunTime] >= #LastSubscriptionDate OR #LastSubscriptionDate IS NULL)
AND
(
(SUBSTRING(s.[ExtensionSettings], LEN('<Name>TO</Name><Value>') + CHARINDEX('<Name>TO</Name><Value>', s.[ExtensionSettings]), CHARINDEX('</Value>', s.[ExtensionSettings], CHARINDEX('<Name>TO</Name><Value>', s.[ExtensionSettings]) + 1) - (LEN('<Name>TO</Name><Value>') + CHARINDEX('<Name>TO</Name><Value>', s.[ExtensionSettings])))
LIKE '%' + #EmailLike + '%' OR #EmailLike IS NULL
)
OR
(
CASE CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings)
WHEN 0 THEN ''
ELSE SUBSTRING(s.ExtensionSettings, LEN('<Name>CC</Name><Value>') + CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.ExtensionSettings, CHARINDEX('<Name>CC</Name><Value>', s.ExtensionSettings) + 1) - (LEN('<Name>CC</Name><Value>') + CHARINDEX('<Name>CC</Name><Value>', s.[ExtensionSettings])))
END
LIKE '%' + #EmailLike + '%'
)
OR
(
CASE CHARINDEX('<Name>BCC</Name><Value>', s.[ExtensionSettings])
WHEN 0 THEN ''
ELSE SUBSTRING(s.[ExtensionSettings], LEN('<Name>BCC</Name><Value>') + CHARINDEX('<Name>BCC</Name><Value>', s.ExtensionSettings), CHARINDEX('</Value>', s.[ExtensionSettings], CHARINDEX('<Name>BCC</Name><Value>', s.[ExtensionSettings]) + 1) - (LEN('<Name>BCC</Name><Value>') + CHARINDEX('<Name>BCC</Name><Value>', s.[ExtensionSettings])))
END
LIKE '%' + #EmailLike + '%')
)
To answer your third question, I would use roles in the report folders to manage permissions.
In SSRS, new roles and adjustments to existing roles must be performed in SQL Server Management studio, SSMS. After opening up SSMS, click on "Connect" and select "Reporting Services…"
Enter your Server Name and login information and then click Connect.
After connecting to the Report Server, open the Security Folder right click on "Roles" and click on "New Role…"
You can create a new role Subscription Editor or Functional Owner and then you can assign permissions to the new roles based on what you want the user(s) to be able to do.
Then on the report manager click on the down arrow for a folder and select "Security"
Then click "New Role Assignment"
Then enter the Active Directory group or an email address and check the new role you created.
Here is a more detailed wiki I wrote for report server permission on MSDN.

Calculate a Slide rate commission per agent with MySQL... AND in ON statement?

I have set up a sqlfiddle for this question : see here
I have an issue calculating a slide rate commission for Agents, based on their Sales (called NGR here).
The commission table is the following:
+----+------------+----------+----------+----------+--------+
| id | tier_min | tier_max | com_rate | dif_rate | agent |
+----+------------+----------+----------+----------+--------+
| 1 | 0 | 100000 | 0.15 | 0.15 | AGENT4 |
| 3 | 100000.001 | 200000 | 0.2 | 0.05 | AGENT4 |
| 4 | 200000.001 | 300000 | 0.25 | 0.05 | AGENT4 |
| 5 | 300000.001 | 500000 | 0.3 | 0.05 | AGENT4 |
| 6 | 500000.001 | 10000000 | 0.35 | 0.05 | AGENT4 |
+----+------------+----------+----------+----------+--------+
For example, if an Agent has $120000 sales in a period, he gets 15% from 0 to 100 000 (15000), 20% from the threshold 100000 to 200000 (20000*20%=4000), total 19 000
The mysql query detailed in the mysqlfiddle details the working formula:
sum((s.NGR - r.tier_min) * r.dif_rate) as SlideCom
And the final query looks like:
+--------+---------+------------+-------+----------+----------+
| Agent | APmonth | FirstMonth | NGR | FIXEDCOM | VARCOM2 |
+--------+---------+------------+-------+----------+----------+
| AGENT1 | 3 | 0 | 16802 | 0 | 2520.327 |
| AGENT2 | 17 | 2 | 7926 | 60 | 1188.975 |
| AGENT3 | 3 | 0 | 6541 | 0 | 981.15 |
| AGENT4 | 4 | 0 | 5513 | 0 | 826.95 |
| AGENT5 | 1 | 0 | 3 | 0 | 0.6 |
| AGENT6 | 1 | 0 | 1 | 0 | 0.21 |
+--------+---------+------------+-------+----------+----------+
My issues:
I cannot fix the issue where i need EACH agent to have its specific sliding scale of commission, and relate the AGENT field in the Commissions table to its corresponding Agent's Sales (NGR). I tried to modified the query adding to
JOIN commissions r ON r.tier_min <= s.NGR AND s.Agent= a.Agent
but it does not work.
Any help on this issue would be a great help since I have been trying to do this for a while on my own with my limited Mysql skills;)
Thanks!
full data in case on sql fiddle issue:
CREATE TABLE commissions
(`id` int, `tier_min` double, `tier_max` double, `com_rate` double, `dif_rate` double, `agent` varchar(50))
;
INSERT INTO commissions
(`id`, `tier_min`, `tier_max`, `com_rate`, `dif_rate`, `agent`)
VALUES
(1, 0, 100000, .15, .15, 'AGENT4'),
(3, 100000.001, 200000, .2, .05, 'AGENT4'),
(4, 200000.001, 300000, .25, .05, 'AGENT4'),
(5, 300000.001, 500000, .3, .05, 'AGENT4'),
(6, 500000.001, 10000000, .35, .05, 'AGENT4')
;
CREATE TABLE Online_customer_activity_v2
(`id` int, `Date` datetime, `Customers` varchar(100), `Agent` varchar(100), `Real_Money` int, `_Bonuses` int, `Total_Bets` int, `Total_Win_Loss` int)
;
INSERT INTO Online_customer_activity_v2
(`id`, `Date`, `Customers`, `Agent`, `Real_Money`, `_Bonuses`, `Total_Bets`, `Total_Win_Loss`)
Values
(6813, '2017-01-01 00:00:00', 'KingOfPop', 'AGENT2',101000,1000,4000,100500),
(6814, '2017-01-01 00:00:00', 'Serena77', 'AGENT4',130000,1000,514500,120000),
(6815, '2017-01-01 00:00:00', 'KerymNY', 'AGENT3',376,0,1267.65,375.93),
(6816, '2017-01-01 00:00:00', 'whatthelol', 'AGENT1',130,0,6233.5,119.4993),
(6817, '2017-01-01 00:00:00', 'Noukashi', 'AGENT2',0,0,343.4,49.8),
(6818, '2017-01-01 00:00:00', 'SeaSunBeach', 'AGENT2',30,0,654.5,30),
(6819, '2017-01-01 00:00:00', 'Rizo_090', 'AGENT3',400,0,2675,-1165),
(6820, '2017-01-02 00:00:00', 'Rizo_090', 'AGENT3',7900,1200,140168,30199)
;
CREATE TABLE Online_playerdatabase_v2
(`id` int, `Player` varchar(50), `Agent` varchar(50), `Sign_Up_Date` varchar(12), `First_Deposit_Date` varchar(18))
;
INSERT INTO Online_playerdatabase_v2
(`id`, `Player`, `Agent`, `Sign_Up_Date`, `First_Deposit_Date`)
VALUES
(75, 'KerymNY', 'AGENT3', '2015-02-21', '2015-02-26'),
(137, 'Rizo_090', 'AGENT3', '2015-10-23', '2015-10-23'),
(286, 'KingOfPop', 'AGENT2', '2016-10-03', '2016-12-21'),
(6, 'Noukashi', 'AGENT2', '2016-07-21', '2016-07-22'),
(294, 'Serena77', 'AGENT4', '2016-10-09', '2017-01-02'),
(160, 'whatthelol', 'AGENT1', '2015-03-01', '2015-03-05'),
(360, 'SeaSunBeach', 'AGENT2', '2016-04-18', '2016-04-18')
;
SELECT
a.Agent ,
t2.APmonth ,
COALESCE(t8.FirstMonth , 0) AS FirstMonth ,
TRUNCATE(a.NGR , 0) AS NGR ,
COALESCE(t8.FirstMonth , 0) * 30 AS FIXEDCOM ,
COALESCE(yy.SlideCom , 0) AS VARCOM2 ,
TRUNCATE(
COALESCE(t8.FirstMonth , 0) * 30 + COALESCE(yy.SlideCom , 0) ,
0
) AS totalCOM
FROM
(
SELECT
Online_customer_activity_v2.Agent ,
sum(
Online_customer_activity_v2._Bonuses
) AS BONUS ,
sum(
Online_customer_activity_v2.Total_Win_Loss
) - sum(
Online_customer_activity_v2._Bonuses
) AS NGR
FROM
Online_customer_activity_v2
WHERE
(
Online_customer_activity_v2.Date BETWEEN '2017-01-01'
AND '2017-01-12'
AND Agent <> 'NOAGENT'
)
GROUP BY
Online_customer_activity_v2.Agent
) a
LEFT JOIN(
SELECT
Agent ,
count(First_Deposit_Date) AS FirstMonth
FROM
Online_playerdatabase_v2
WHERE
Online_playerdatabase_v2.First_Deposit_Date BETWEEN '2017-01-01'
AND '2017-01-12'
GROUP BY
Agent
) t8 ON a.Agent = t8.Agent
LEFT JOIN(
SELECT
Online_customer_activity_v2.Agent ,
COUNT(DISTINCT(Customers)) AS APmonth
FROM
Online_customer_activity_v2
WHERE
(
Online_customer_activity_v2.Date BETWEEN '2017-01-01'
AND '2017-01-12'
AND Agent <> 'NOAGENT'
)
AND Online_customer_activity_v2.Total_Bets > 0
GROUP BY
Agent
) AS t2 ON a.Agent = t2.Agent
LEFT JOIN(
SELECT
s.Agent ,
sum((s.NGR - r.tier_min) * r.dif_rate) SlideCom
FROM
(
SELECT
Date ,
Online_customer_activity_v2.Agent ,
sum(
Online_customer_activity_v2.Total_Win_Loss
) - sum(
Online_customer_activity_v2._Bonuses
) AS NGR
FROM
Online_customer_activity_v2
WHERE
Agent <> 'NOAGENT'
AND (Date BETWEEN '2017-01-01'
AND '2017-01-12')
GROUP BY
Agent ,
date_format(Date , '%Y-%m')
) s
JOIN commissions r ON r.tier_min <= s.NGR
GROUP BY
Agent
) yy ON a.Agent = yy.Agent
ORDER BY
NGR DESC;
I think this is you are looking for:
SeLeCt t5.Agent,t6.APmonth,t6.FirstMonth,t5.NGR,t5.toRate,t5.comm FrOm
(
SELECT t2.Agent,t2.NGR,ROUND(sum(t2.toRate),2) AS 'toRate',ROUND(sum(t2.comm),2) AS 'comm' FROM
(
select t1.Agent,t1.NGR,if(t1.NGR-c.tier_min>0,
if(t1.NGR>c.tier_max,c.tier_max-c.tier_min,t1.NGR-c.tier_min),
0) as 'toRate',
if(t1.NGR-c.tier_min>0,
if(t1.NGR>c.tier_max,c.tier_max-c.tier_min,t1.NGR-c.tier_min),
0)*c.com_rate as 'comm'
from myDB.commissions c ,
(
SELECT ocav2.Agent, sum(ocav2.Total_Win_Loss - ocav2._Bonuses) as 'NGR'
FROM myDB.Online_customer_activity_v2 ocav2
GROUP BY ocav2.Agent
) t1
where c.agent = t1.Agent
) t2
GROUP BY t2.Agent
) t5 LeFt JoIn
(
select t3.Agent,t3.APmonth,if(t4.FirstMonth is null,0,t4.FirstMonth) as 'FirstMonth' from
(
SELECT oca.Agent,COUNT(DISTINCT(oca.Customers)) AS 'APmonth'
FROM Online_customer_activity_v2 oca
WHERE oca.Total_Bets>0 AND oca.Date BETWEEN '2017-01-01' AND '2017-01-12'
GROUP BY oca.Agent
) t3 LEFT JOIN
(
SELECT
opv2.Agent ,
count(opv2.First_Deposit_Date) AS 'FirstMonth'
FROM
Online_playerdatabase_v2 opv2
WHERE
opv2.First_Deposit_Date BETWEEN '2017-01-01' AND '2017-01-12'
GROUP BY
opv2.Agent
) t4
on t3.Agent=t4.Agent
) t6 On t5.Agent=t6.Agent
;
Remember change "myDB" by your database
Given
drop table if exists t;
create table t( id int, tier_min int, tier_max int, com_rate decimal(10,2), dif_rate decimal(10,2), agent varchar(10));
truncate table t;
insert into t values
( 1 , 0 , 100000, 0.15 , 0.15 , 'AGENT4'),
( 3 , 100000.001 , 200000 , 0.2 , 0.05 , 'AGENT4'),
( 4 , 200000.001 , 300000 , 0.25 , 0.05 , 'AGENT4'),
( 5 , 300000.001 , 500000 , 0.3 , 0.05 , 'AGENT4'),
( 6 , 500000.001 , 10000000 , 0.35 , 0.05 , 'AGENT4'),
( 7 , 0 , 10000 , 0.15 , 0.15 , 'AGENT1'),
( 8 , 10000.001 , 15000 , 0.2 , 0.05 , 'AGENT1'),
( 9 , 15000.001 , 20000 , 0.3 , 0.05 , 'AGENT1'),
( 10 , 0 , 100000, 0.15 , 0.15 , 'AGENT6'),
( 11 , 100000.001 , 200000 , 0.2 , 0.05 , 'AGENT6'),
( 12 , 200000.001 , 300000 , 0.25 , 0.05 , 'AGENT6'),
( 13 , 300000.001 , 500000 , 0.3 , 0.05 , 'AGENT6'),
( 14 , 500000.001 , 10000000 , 0.35 , 0.05 , 'AGENT6')
;
drop table if exists agent;
create table agents ( Agent varchar(10) , APmonth int, FirstMonth int, NGR int, FIXEDCOM int, VARCOM2 decimal(10,2));
truncate table agents;
insert into agents values
( 'AGENT1' , 3 , 0 , 16802 , 0 , 2520.327),
( 'AGENT2' , 17 , 2 , 7926 , 60 , 1188.975),
( 'AGENT3' , 3 , 0 , 6541 , 0 , 981.15),
( 'AGENT4' , 4 , 0 , 5513 , 0 , 826.95),
( 'AGENT5' , 1 , 0 , 3 , 0 , 0.6),
( 'AGENT6' , 1 , 0 , 750000, 0 , 0.21);
Try this
select u.sagent, u.ngr,
u.amt1+u.amt2+u.amt3+u.amt4+u.amt5 as Commamt,
u.com1+u.com2+u.com3+u.com4+u.com5 as Comm
from
(
SELECT T.SAGENT,T.NGR,t.comrate1,
if(t.ngr <= t.maxtier1 , t.ngr ,t.maxtier1) amt1,
ifnull(t.comrate1 * if(t.ngr <= t.maxtier1 , t.ngr ,t.maxtier1),0) com1,
t.comrate2,
if(t.ngr >= t.mintier2 and t.ngr <= t.maxtier2, t.ngr - t.maxtier1,if(t.ngr > t.mintier3,t.maxtier2 - t.maxtier1,0)) amt2,
ifnull(t.comrate2 * if(t.ngr >= t.mintier2 and t.ngr <= t.maxtier2, t.ngr - t.maxtier1,if(t.ngr > t.mintier3,t.maxtier2 - t.maxtier1,0)),0) com2,
t.comrate3,
if(t.ngr >= t.mintier3 and t.ngr <= t.maxtier3, t.ngr - t.maxtier2,if(t.ngr > t.mintier4,t.maxtier3 - t.maxtier2,0)) amt3,
ifnull(t.comrate3 * if(t.ngr >= t.mintier3 and t.ngr <= t.maxtier3, t.ngr - t.maxtier2,if(t.ngr > t.mintier4,t.maxtier3 - t.maxtier2,0)),0) com3,
t.comrate4,
if(t.ngr >= t.mintier4 and t.ngr <= t.maxtier4, t.ngr - t.maxtier3,if(t.ngr > t.mintier5,t.maxtier4 - t.maxtier3,0)) amt4,
ifnull(t.comrate4 * if(t.ngr >= t.mintier4 and t.ngr <= t.maxtier4, t.ngr - t.maxtier3,if(t.ngr > t.mintier5,t.maxtier4 - t.maxtier3,0)),0) com4,
t.comrate5,
if(t.ngr >= t.mintier5 and t.ngr <= t.maxtier5, t.ngr - t.maxtier4,if(t.ngr > 9999999999,t.maxtier5 - t.maxtier4,0)) amt5,
ifnull(t.comrate5 * if(t.ngr >= t.mintier5 and t.ngr <= t.maxtier5, t.ngr - t.maxtier4,if(t.ngr > 9999999999,t.maxtier5 - t.maxtier4,0)),0) com5
FROM
(
select s.agent SAGENT,a.*,
max(case when s.rn = 1 then s.tier_min end) mintier1,
max(case when s.rn = 1 then s.tier_max end) maxtier1,
max(case when s.rn = 1 then s.com_rate end) comrate1,
max(case when s.rn = 2 then s.tier_min end) mintier2,
max(case when s.rn = 2 then s.tier_max end) maxtier2,
max(case when s.rn = 2 then s.com_rate end) comrate2,
max(case when s.rn = 3 then s.tier_min end) mintier3,
max(case when s.rn = 3 then s.tier_max end) maxtier3,
max(case when s.rn = 3 then s.com_rate end) comrate3,
max(case when s.rn = 4 then s.tier_min end) mintier4,
max(case when s.rn = 4 then s.tier_max end) maxtier4,
max(case when s.rn = 4 then s.com_rate end) comrate4,
max(case when s.rn = 5 then s.tier_min end) mintier5,
max(case when s.rn = 5 then s.tier_max end) maxtier5,
max(case when s.rn = 5 then s.com_rate end) comrate5
from
(
select t.*,
if (t.agent <> #p ,#rn:=1,#rn:=#rn+1) rn,
#p:=t.agent
from (select #rn:=0,#p:='') rn,t
order by t.agent, t.id
) s
join agents a on a.agent = s.agent
group by s.agent
) T
) u
Note I am assuming a max number of rates as 5
The sub query s allocates a row number to each rate per agent (1-5) which is then joined and pivoted to create 1 row per agent.The sub query t then works out the amount that falls into each commission band and the value of the commission. The outer query then simply totals the amounts that fall into each band as a cross check and the final commission amount.