Get weekly average for work days in each week - sql-server

I have to find weekly average from table given below (only work days - monday to friday). Number I am searching average is AVAI_NUM. I have to calculate average of AVAI_NUM for each week in given period.
Example:
If period is january 2016:
declare #dDateFrom date = cast('2016-01-01' as date)
declare #dDateTo date = cast('2016-01-31' as date)
Table looks like this:
declare #scavai table
(
avai_key int,
avai_dat date,
avai_num int
)
Fill table with data:
insert into #scavai(avai_Key, avai_dat, avai_num)
select 1, cast('2016-01-01' as date), 3
union all
select 1, cast('2016-01-02' as date), 2
union all
select 1, cast('2016-01-03' as date), 5
union all
select 1, cast('2016-01-04' as date), 6
union all
select 1, cast('2016-01-05' as date), 1
union all
select 1, cast('2016-01-06' as date), 8
union all
select 1, cast('2016-01-07' as date), 4
union all
select 1, cast('2016-01-08' as date), 3
union all
select 1, cast('2016-01-09' as date), 2
union all
select 1, cast('2016-01-10' as date), 1
union all
select 1, cast('2016-01-11' as date), 9
union all
select 1, cast('2016-01-12' as date), 7
union all
select 1, cast('2016-01-13' as date), 3
union all
select 1, cast('2016-01-14' as date), 8
union all
select 1, cast('2016-01-15' as date), 3
union all
select 1, cast('2016-01-16' as date), 2
union all
select 1, cast('2016-01-17' as date), 3
union all
select 1, cast('2016-01-18' as date), 1
union all
select 1, cast('2016-01-19' as date), 4
union all
select 1, cast('2016-01-20' as date), 5
union all
select 1, cast('2016-01-21' as date), 7
union all
select 1, cast('2016-01-22' as date), 3
union all
select 1, cast('2016-01-23' as date), 3
union all
select 1, cast('2016-01-25' as date), 3
union all
select 1, cast('2016-01-26' as date), 3
I know how to calculate number of weeks in given period:
select DATEDIFF(ww, '2016-01-01', '2016-01-31')
But I don't know how to calculate AVAI_NUM for work days in each week and divide this with number of days in particular week and then summarize all of this and divide with number of weeks?

try,
select *,
AVG(cast(avai_num as decimal)) over
(partition by datepart(week, avai_dat) order by (select 1)) avg1
from #scavai
where avai_dat between #dDateFrom and #dDateTo
order by avai_dat

Related

TSQL: Continuous period for whole year / each month

I try to find all Cust who have membership for at least for one day in each month during 2018.
I came up with solution checking their membership at the beginning / middle / end end of each month like in snippet below, but trying to find more intelligent solution.
I know that I can use tally table for each of 365 days to check this but probably there is more elegant solution ? I'm bit new to SQL, I think I'm missing something in GROUPing area.
In the code snippet shown below, both Cust have at least one day membership.
Desired output:
CustID
------
1
22
Code:
with data as
(
select *
from (values (1, 1, '2017-12-11', '2018-01-16'), (1, 22, '2018-01-28', '2018-03-9' ), (1, 333, '2018-03-1', '2018-12-31') , -- island
(22, 1, '2017-12-31', '2018-01-11'), (22, 2, '2017-2-11', '2019-12-31')) as t (CustID, ContractID, StartDD, EndDD) ---
)
select
isdate(startDD), isdate(EndDD)
from
data
), gaps as
(
select
*,
datediff(day, lag(EndDD, 1, StartDD) over (partition by CustID order by StartDD), StartDD) as BreakDD -- negative is island
from
data
)
select
*,
datepart(month,StartDD) mmS , datepart(month,EndDD) mmE
from
gaps
-- and was active any 1+ day during each of the 12 months in 2018 ????
where
1 = 1
/* and (cast('1/1/2018' as date) between StartDD and EndDD
or cast('1/15/2018' as date) between StartDD and EndDD
or cast('1/31/2018' as date) between StartDD and EndDD)
---- etc.. for each month
and ( cast('12/1/2018' as date) between StartDD and EndDD
or cast('12/15/2018' as date) between StartDD and EndDD
or cast('12/31/2018' as date) between StartDD and EndDD
)
*/
--select CustID, max(BreakDD) Max_Days
--from gaps
--group by CustID
Try this answer.
First create a function to return all the month and year between the given dates.
Function:
--SELECT * FROM dbo.Fn_GetMonthYear('2017-12-11','2018-01-16')
ALTER FUNCTION dbo.Fn_GetMonthYear(#StartDate DATETIME,#EndDate DATETIME)
RETURNS TABLE
AS
RETURN(
SELECT DATEPART(MONTH, DATEADD(MONTH, x.number, #StartDate)) AS [Month]
,DATEPART(YEAR, DATEADD(MONTH, x.number, #StartDate)) AS [Year]
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate)
)
Table Schema:
CREATE TABLE #t(CustID INT, ContractID INT, StartDD date, EndDD date)
INSERT INTO #t values (1, 1, '2017-12-11', '2018-01-16'), (1, 22, '2018-01-28', '2018-03-9' ), (1, 333, '2018-03-1', '2018-12-31') , -- island
(22, 1, '2017-12-31', '2018-01-11'), (22, 2, '2017-2-11', '2019-12-31')
Here is the T-SQL Query for your requirement.
SELECT CustID
,COUNT(DISTINCT [Month]) NoOfMonths
FROM(
SELECT *
FROM #t t
CROSS APPLY dbo.Fn_GetMonthYear(StartDD,EndDD)
)D
WHERE [Year] = 2018
GROUP BY CustID
HAVING COUNT(DISTINCT [Month])=12
Result:
CustID NoOfMonths
1 12
22 12
find all Cust who have membership for at least for one day in each
month during 2018
I think this mean that data must be present between '2018-01-01' and '2018-12-31' for each custid.
CREATE TABLE #t(CustID INT, ContractID INT, StartDD date, EndDD date)
INSERT INTO #t values (1, 1, '2017-12-11', '2018-01-16'), (1, 22, '2018-01-28', '2018-03-9' ), (1, 333, '2018-03-1', '2018-12-31') , -- island
(22, 1, '2017-12-31', '2018-01-11'), (22, 2, '2017-2-11', '2019-12-31')
declare #From Datetime='2018-01-01'
declare #To datetime='2018-12-31'
;with CTE as
(
select CustID,min(StartDD)StartDD
,max(EndDD)EndDD
from #t
group by CustID
)
select CustID,StartDD
,EndDD
from CTE
where StartDD<=#From and EndDD>=#To
This script is not tested across all sample data.
But logic is clear.So it can be corrected accordingly.
So tell for what sample data it is not working.

Get start and end date by month name, not month number

How do I get start date and end date of a month by month name? Not by date, not by month number.
For example, this gets me first day of current month. Input is a date type, not string like I want it to be.
SELECT DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)
What I want is to input month name in string like 'March' not 3 and get 2016/03/01 and 2016/03/31. I'd really be overwhelmed and appreciate any/all help.
You can create a CTE to get the month number:
DECLARE #month VARCHAR(10) = 'March';
WITH CteMonths(n, m) AS(
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'April' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'June' UNION ALL
SELECT 7, 'July' UNION ALL
SELECT 8, 'August' UNION ALL
SELECT 9, 'September' UNION ALL
SELECT 10, 'October' UNION ALL
SELECT 11, 'November' UNION ALL
SELECT 12, 'December'
)
SELECT
DATEADD(MONTH, n - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)),
DATEADD(DAY, -1, DATEADD(MONTH, n, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)))
FROM CteMonths
WHERE m = #month

Get contiguous date ranges grouped into a single line

I have a table which holds a lot of rows (Currently, 500K, expected to rise to 15 Million in the next 3 years). The table holds payments made for a certain event for a specific day. And event can have 1 or many payments for the same day, but the payments on the same day must have different PaymentTypes.
Below is a table variable creation that creates the basic data (Input), and then a hardcoded select which is the expected output. I need to group continuous date ranges for a payment type, for a placement, in one row, with a From and To date, and then when there's a break - no rows, and then for the next date range.
For example:
Placement 1 got payments from the 1st to the 2nd (2 days) for Payment type 5, and then from the 4th until the 6th for the same type. Therefore, two rows. Payment type 1 also got a payment for the 1st to the 3rd for payment type 10. So, that is another row.
DECLARE #Temp TABLE
(
Id INT NOT NULL IDENTITY(1,1),
PlacementId INT NOT NULL,
PaymentTypeId INT NOT NULL,
DateValue DATETIME NOT NULL,
Amount DECIMAL(16,2) NOT NULL
)
INSERT INTO #Temp (PlacementId, PaymentTypeId, DateValue, Amount)
SELECT 1, 5, '01-JAN-2015', 100 UNION
SELECT 1, 5, '02-JAN-2015', 150 UNION
SELECT 1, 5, '04-JAN-2015', 78 UNION
SELECT 1, 5, '05-JAN-2015', 89 UNION
SELECT 1, 5, '06-JAN-2015', 22 UNION
SELECT 1, 10, '01-JAN-2015', 10 UNION
SELECT 1, 10, '02-JAN-2015', 10 UNION
SELECT 1, 10, '03-JAN-2015', 15 UNION
SELECT 2, 5, '01-JAN-2015', 200 UNION
SELECT 2, 5, '02-JAN-2015', 5 UNION
SELECT 2, 5, '03-JAN-2015', 50 UNION
SELECT 3, 5, '01-JAN-2015', 80 UNION
SELECT 4, 5, '07-JAN-2015', 100 UNION
SELECT 4, 5, '08-JAN-2015', 12 UNION
SELECT 4, 5, '12-JAN-2015', 66 UNION
SELECT 4, 5, '14-JAN-2015', 4 UNION
SELECT 5, 10, '08-JAN-2015', 10
SELECT * FROM #Temp
SELECT 1 AS PlacementId, 5 AS PaymentTypeId, '2015-01-01' AS FromDate, '2015-01-02' AS ToDate, 250 AS Amount UNION
SELECT 1, 10, '2015-01-01', '2015-01-03', 35 UNION
SELECT 1, 5, '2015-01-04', '2015-01-06', 189 UNION
SELECT 2, 5, '2015-01-01', '2015-01-03', 255 UNION
SELECT 3, 5, '2015-01-01', '2015-01-01', 80 UNION
SELECT 4, 5, '2015-01-07', '2015-01-08', 112 UNION
SELECT 4, 5, '2015-01-12', '2015-01-12', 66 UNION
SELECT 4, 5, '2015-01-14', '2015-01-14', 4 UNION
SELECT 5, 10, '2015-01-08', '2015-01-08', 10
Note, there is a NCI on PlacementID and PaymentTypeID.
We're doing it at the moment with a crazy load of cursors, and are having extreme speed issues. (The 500K lines takes 4 minutes to process).
Is there an efficient method to achieve the desired output?
This is a problem called Grouping Islands of Contiguous Dates. Read this article be Jeff Moden for more info.
SQL Fiddle
;WITH Cte AS(
SELECT *,
RN = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY PlacementId, PaymentTypeId ORDER BY DateValue), DateValue)
FROM #Temp
)
SELECT
PlacementId,
PaymentTypeId,
FromDate = MIN(DateValue),
ToDate = MAX(DateValue),
Amount = SUM(Amount)
FROM Cte
GROUP BY PlacementId, PaymentTypeId, RN
ORDER BY PlacementId, PaymentTypeId, FromDate

Select rows based on every nth interval of time

I have a table with a primary key (bigint), datetime, value, foreignKey to configuration tabel that consists of 100,000's of rows. I want to be able to obtain a row for a variable time interval. For example.
Select Timestamp, value from myTable where configID=3
AND{most recent for 15 min interval}
I have a CTE query that returns multiple rows for the interval interval
WITH Time_Interval(timestamp, value, minutes)
AS
(
Select timestamp, value, DatePart(Minute, Timestamp) from myTable
Where Timestamp >= '12/01/2012' and Timestamp <= 'Jan 10, 2013' and
ConfigID = 435 and (DatePart(Minute, Timestamp) % 15) = 0
)
Select Timestamp, value, minutes from Time_Interval
group by minutes, value, timestamp
order by Timestamp
such as:
2012-12-19 18:15:22.040 6.98 15
2012-12-19 18:15:29.887 6.98 15
2012-12-19 18:15:33.480 7.02 15
2012-12-19 18:15:49.370 7.01 15
2012-12-19 18:30:41.920 6.95 30
2012-12-19 18:30:52.437 6.93 30
2012-12-19 19:15:18.467 7.13 15
2012-12-19 19:15:34.250 7.11 15
2012-12-19 19:15:49.813 7.12 15
But as can be seen there are 4 for the 1st 15 minute interval, 2 for the next interval, etc... Worse,
If no data was obtain at an exact times stamp of 15 minutes, then there will be no value.
What I want is the most recent value for a fifteen minute interval... if if the only data for that intervall occurred at 1 second after the start of the interval.
I was thinking of Lead/over but again... the rows are not orgainzed that way. Primary Key is a bigInt and is a clustered Index. Both the timstamp column and ConfigID columns are Indexed. The above query returns 4583 rows in under a second.
Thanks for any help.
Try this on for size. It will even handle returning one row for instances when you have multiple timestamps for a given interval.
NOTE: This assumes your Bigint PK column is named: idx. Just substitute where you see "idx" if it is not.
;WITH Interval_Helper([minute],minute_group)
AS
(
SELECT 0, 1 UNION SELECT 1, 1 UNION SELECT 2, 1 UNION SELECT 3, 1 UNION SELECT 4, 1
UNION SELECT 5, 1 UNION SELECT 6, 1 UNION SELECT 7, 1 UNION SELECT 8, 1 UNION SELECT 9, 1
UNION SELECT 10, 1 UNION SELECT 11, 1 UNION SELECT 12, 1 UNION SELECT 13, 1 UNION SELECT 14, 1
UNION SELECT 15, 2 UNION SELECT 16, 2 UNION SELECT 17, 2 UNION SELECT 18, 2 UNION SELECT 19, 2
UNION SELECT 20, 2 UNION SELECT 21, 2 UNION SELECT 22, 2 UNION SELECT 23, 2 UNION SELECT 24, 2
UNION SELECT 25, 2 UNION SELECT 26, 2 UNION SELECT 27, 2 UNION SELECT 28, 2 UNION SELECT 29, 2
UNION SELECT 30, 3 UNION SELECT 31, 3 UNION SELECT 32, 3 UNION SELECT 33, 3 UNION SELECT 34, 3
UNION SELECT 35, 3 UNION SELECT 36, 3 UNION SELECT 37, 3 UNION SELECT 38, 3 UNION SELECT 39, 3
UNION SELECT 40, 3 UNION SELECT 41, 3 UNION SELECT 42, 3 UNION SELECT 43, 3 UNION SELECT 44, 3
UNION SELECT 45, 4 UNION SELECT 46, 4 UNION SELECT 47, 4 UNION SELECT 48, 4 UNION SELECT 49, 4
UNION SELECT 50, 4 UNION SELECT 51, 4 UNION SELECT 52, 4 UNION SELECT 53, 4 UNION SELECT 54, 4
UNION SELECT 55, 4 UNION SELECT 56, 4 UNION SELECT 57, 4 UNION SELECT 58, 4 UNION SELECT 59, 4
)
,Time_Interval([timestamp], value, [date], [hour], minute_group)
AS
(
SELECT A.[Timestamp]
,A.value
,CONVERT(smalldatetime, CONVERT(char(10), A.[Timestamp], 101))
,DATEPART(HOUR, A.[Timestamp])
,B.minute_group
FROM myTable A
JOIN Interval_Helper B
ON (DATEPART(minute, A.[Timestamp])) = B.[minute]
AND A.[Timestamp] >= '12/01/2012'
AND A.[Timestamp] <= '01/10/2013'
AND A.ConfigID = 435
)
,Time_Interval_TimeGroup([date], [hour], [minute], MaxTimestamp)
AS
(
SELECT [date]
,[hour]
,minute_group
,MAX([Timestamp]) as MaxTimestamp
FROM Time_Interval
GROUP BY [date]
,[hour]
,minute_group
)
,Time_Interval_TimeGroup_Latest(MaxTimestamp, MaxIdx)
AS
(
SELECT MaxTimestamp
,MAX(idx) as MaxIdx
FROM myTable A
JOIN Time_Interval_TimeGroup B
ON A.[Timestamp] = B.MaxTimestamp
GROUP BY MaxTimestamp
)
SELECT A.*
FROM myTable A
JOIN Time_Interval_TimeGroup_Latest B
ON A.idx = B.MaxIdx
ORDER BY A.[timestamp]
This is another take on the clever time group function from #MntManChris below:
CREATE FUNCTION dbo.fGetTimeGroup (#DatePart tinyint, #Date datetime)
RETURNS int
AS
BEGIN
RETURN CASE #DatePart
WHEN 1 THEN DATEPART(mi, #Date)
WHEN 2 THEN DATEPART(mi, #Date)/5 + 1 -- 5 min
WHEN 3 THEN DATEPART(mi, #Date)/15 + 1 -- 15 min
WHEN 4 THEN DATEPART(mi, #Date)/30 + 1 -- 30 min
WHEN 5 THEN DATEPART(hh, #Date) -- hr
WHEN 6 THEN DATEPART(hh, #Date)/6 + 1 -- 6 hours
WHEN 7 THEN DATEPART(hh, #Date)/12 + 1 -- 12 hours
WHEN 8 THEN DATEPART(d, #Date) -- day
ELSE -1
END
END
If you want to partition in 15 minute interval use datediff in minutes and divide by 15.
And use that partition to rank each interval.
WITH myTbl AS
(
SELECT
timestamp, value,
RANK() OVER (PARTITION BY (DATEDIFF(Mi,0, Timestamp)/15) ORDER BY Timestamp desc) RK
FROM myTable
--WHERE Timestamp BETWEEN '' AND ''
)
SELECT * FROM myTble
WHERE RK <= 1
As my comment above says I've used Rob's answer but implmented a user function to eliminate the Interval_Helper table and the first join. Here is the code for the user function.
BEGIN
DECLARE #Ans integer
if #DatePart = 1 -- min
return DATEPART(mi, #Date)
if #DatePart = 2 -- 5 min
return DatePart(mi,#Date)/5 + 1
if #DatePart = 3 -- 15 min
return DatePart(mi,#Date)/15 + 1
if #DatePart = 4 -- 30min
return DatePart(mi,#Date)/30 + 1
if #DatePart = 5 -- hr
return DATEPART(hh, #Date)
if #DatePart = 6 -- 6 hours
return DATEPART(hh, #Date)/6 + 1
if #DatePart = 7 -- 12 hours
return DATEPART(hh, #Date)/12 + 1
if #DatePart = 8 -- day
return DATEPART(d, #Date)
return -1
END
This then made the Time_Interval table look like
;WITH Time_Interval([timestamp], value, [date], [day], time_group)
AS
(
SELECT A.[Timestamp]
,A.value
,CONVERT(smalldatetime, CONVERT(char(10), A.[Timestamp], 101))
,DATEPART(dd, A.[Timestamp])
,dbo.fGetTimeGroup(#tInterval, A.[Timestamp]) as 'time_group'
FROM myTable A
where
A.[Timestamp] >= '12/01/2012'
AND A.[Timestamp] <= '01/10/2013'
AND A.ConfigID= 435
)
Since there is a switch from "hours" to "days" as the #TimeInterval goes from 1hr to 6hr, or 12hr or every day. I also had to have the Time_Interval_TimeGroup table switch from grouping by [hour] to grouping by [day] and of course having this in the select list.
Since this is part of a much larger abstract DB schema where both the table in question and the db are functions of the ConfigID and thus required dynamic SQL, implmenting this switch in grouping was not an issue, I simply implmented two different dynSql sections based on the value of #TimeInterval
Thanks

Report Server aggregation over groups by line

Maybe this is a newbie question, but
Imagine I have a report that shows the sales-order list pr sales-rep, itemized
to sku level, and want to show how many percent of the total sale of 1 sku, the sales-rep has sold.
I.e.
Sales-person
List of orders
- List of items no sold: 5 out of this months total 942
Example:
John Doe
- Order #12312
- SKU SP1231 Sold 5 . Month total 445
- SKU SP4141 Sold 63 . Month total 300
Emma Doe
- Order #123324
- SKU SP1231 Sold 65 . Month total 445
- SKU SP4141 Sold 2 . Month total 300
etc
The Month total figure is the number of items sold of that particular sku in the total reporting period.
How do I go about adding this number? If I use Fields!TotalAmount.Value it gives the total as the group'ed total. i.e. how many of sku Y was sold on order X by sales-rep Z.
I need the global total of sales of that particular SKU.
If i say SUM(Fields!Amount,Nothing) to set global scope, it gives the sum of ALL sku's, not just the sku in question.
How do I do this?
EDIT
The Report Server is SSRS, the report uses a shared Datasource that is a Report Model already hosted on the reporting server, which points to a SQL Server database with
the contents.
You didn't say what DBMS you are using (not Oracle clearly from the Fields!Amount syntax). Does this work for your DBMS?:
with sku_sales as
( select sku, sum(value) as sku_value
from sales
group by sku
)
select sales.salesperson, sum(sales.value), sku_sales.sku_value
from sales
join sku_sales on sku_sales.sku = sales.sku
group by sales.salesperson, sku_sales.sku_value
What would I do is select Sku total sum in your report dataset using comma separated lists:
-- testing data
DECLARE #Order TABLE (ID INT, SalesRepID INT, Date DATETIME)
INSERT INTO #Order
SELECT 1, 1, GETDATE() UNION
SELECT 2, 2, GETDATE() UNION
SELECT 3, 1, GETDATE() UNION
SELECT 4, 1, GETDATE() UNION
SELECT 5, 2, GETDATE()
DECLARE #OrderDetail TABLE (ID INT, OrderID INT, SkuID INT, SkuCount INT)
INSERT INTO #OrderDetail
SELECT 1, 1, 1, 10 UNION
SELECT 2, 1, 2, 5 UNION
SELECT 3, 1, 3, 20 UNION
SELECT 4, 1, 4, 10 UNION
SELECT 5, 2, 1, 15 UNION
SELECT 6, 2, 2, 25 UNION
SELECT 7, 2, 3, 15 UNION
SELECT 8, 3, 1, 15 UNION
SELECT 9, 3, 1, 10 UNION
SELECT 10, 3, 3, 10 UNION
SELECT 11, 3, 4, 15 UNION
SELECT 12, 4, 1, 5
DECLARE #Sku TABLE (ID INT, SkuCode VARCHAR(10))
INSERT INTO #Sku
SELECT 1, 'SP1233' UNION
SELECT 2, 'SP2262' UNION
SELECT 3, 'SP1531' UNION
SELECT 4, 'SP4235'
DECLARE #SalesRep TABLE (ID INT, SalesRepName VARCHAR(20))
INSERT INTO #SalesRep
SELECT 1, 'John Doe' UNION
SELECT 2, 'Emma Doe'
-- filters for testing
DECLARE #StartDate DATETIME, #EndDate DATETIME
SELECT #StartDate = GETDATE(), #EndDate = GETDATE()
DECLARE #SkuIDList VARCHAR(8000), #SkuSumList VARCHAR(8000)
SELECT #SkuIDList = '', #SkuSumList = ''
--gether all sku IDs and Sum in two comma separated list
SELECT #SkuIDList = #SkuIDList + CONVERT(VARCHAR, OD.SkuID) + ',',
#SkuSumList = #SkuSumList + CONVERT(VARCHAR, SUM(OD.SkuCount)) + ','
FROM #Order O
INNER JOIN #OrderDetail OD ON O.ID = OD.OrderID
WHERE O.Date BETWEEN #StartDate AND #EndDate
GROUP BY OD.SkuID
-- remove last ','
SELECT #SkuIDList = SUBSTRING(#SkuIDList, 0, LEN(#SkuIDList)),
#SkuSumList = SUBSTRING(#SkuSumList, 0, LEN(#SkuSumList))
-- include thouse lists in the main select for your report dataset
SELECT O.ID, OD.SkuID, O.SalesRepID, SR.SalesRepName, S.SkuCode,
OD.SkuCount, #SkuIDList AS SkuIDs, #SkuSumList AS SkuSums
FROM #Order O
INNER JOIN #OrderDetail OD ON O.ID = OD.OrderID
INNER JOIN #Sku S ON OD.SkuID = S.ID
INNER JOIN #SalesRep SR ON O.SalesRepID = SR.ID
WHERE O.Date BETWEEN #StartDate AND #EndDate
Then you can use some custome code to retrieve sum value by sku ID (I have to write in C# currently, you easely convert it to VB):
public int GetSkuSum(string skuSumCSV, string skuIDCSV, int searchSkuID)
{
string[] strSkuSum = skuSumCSV.Split(',');
string[] strSkuID = skuIDCSV.Split(',');
for (int i = 0; i < strSkuID.Length; i++)
{
if (Convert.ToInt32(strSkuID[i].Trim()) == searchSkuID)
{
return Convert.ToInt32(strSkuSum[i]);
}
}
return 0;
}
Then use it in your textbox Value expression:
=Code.GetSkuSum(Fields!SkuIDs.Value,Fields!SkuSums.Value,Fields!SkuID.Value)

Resources