Getting Average Sales by passing dynamic datacolumn

  • I have a webform where the user sees a dropdown with sales column like NetSales, WeeklySales, DailySales and so on. Whatever user selects, I take this value and pass it as a parameter to a stored procedure that would then get the average sales for the column they select from the dropdown. To make this work, I am first trying to get the stored procedure executed. But I have been getting errors.

    Here is my sp.

    ALTER PROCEDURE SA_STPR_Reports_AverageSales

    @startDate datetime,

    @endDate datetime,

    @SearchTerm varchar(255)

    AS

    BEGIN

    SELECTu.FirstName + ' ' + u.LastName AS Name,

    s.WeekOf,

    AVG(CAST(@SearchTerm AS decimal)) AS AvgSales

    FROMSales s

    INNER JOIN User_Stores us ON us.StoreId = s.StoreId

    INNER JOIN Users u ON u.UserId = us.UserId

    INNER JOIN User_Roles ur ON ur.UserId = u.UserId

    WHEREs.WeekOf BETWEEN @startDate AND @endDate

    AND@SearchTerm IS NOT NULL

    ANDur.RoleId = 3

    Group BY u.FirstName, u.LastName, s.WeekOf

    END

    When I try to execute this sp by passing some parameters on sql server 2005 query window, I get the following error.

    SA_STPR_Reports_AverageSales '4/1/2009', '5/1/2009', 'WeeklySales'

    Errormessage : Error converting data type varchar to numeric.

  • You will not be able to do this without creating some dynamic SQL inside the procedure...

    Something like this might work...

    ALTER PROCEDURE SA_STPR_Reports_AverageSales

    @startDate datetime,

    @endDate datetime,

    @SearchTerm varchar(255)

    AS

    BEGIN

    DECLARE @SQL NVARCHAR(4000)

    SELeCT @sql = '

    SELECT u.FirstName + '' '' + u.LastName AS Name,

    s.WeekOf,

    AVG(CAST( ' + @SearchTerm + 'AS decimal)) AS AvgSales

    FROM Sales s

    INNER JOIN User_Stores us ON us.StoreId = s.StoreId

    INNER JOIN Users u ON u.UserId = us.UserId

    INNER JOIN User_Roles ur ON ur.UserId = u.UserId

    WHERE s.WeekOf BETWEEN @startDate AND @endDate

    AND ' + @SearchTerm + ' IS NOT NULL

    AND ur.RoleId = 3

    Group BY u.FirstName, u.LastName, s.WeekOf'

    EXECUTE @SQL

    END

    But remember you are modifying the query inside of the procedure. You may see some performance issues based on the size of data you are working with as you are modifying the Where statement with various requests... One thing that may help would be to remove the IS NOT NULL requirement. Average disregards NULL values as per BOL. Also, just as a side note, make sure you think about not just dates, but the time portion of your end date since you are using between.

    -Luke.

    To help us help you read this[/url]For better help with performance problems please read this[/url]

  • Thanks Luke, I will try this and will let you know.

  • Hey Luke,

    I get this error when I execute the stored proc.

    The name 'SELECT u.FirstName + ' ' + u.LastName AS Name,

    s.WeekOf,

    AVG(CAST( WeeklySalesAS decimal)) AS AvgSales

    FROM Sales s

    INNER JOIN User_Stores us ON us.StoreId = s.StoreId

    INNER JOIN Users u ON u.UserId = us.UserId

    INNER JOIN User_Roles ur ON ur.UserId = u.UserId

    WHERE s.WeekOf BETWEEN @startDate AND @endDate

    AND WeeklySales IS NOT NULL

    AND ur.RoleId = 3

    Group BY u.FirstName, u.LastName, s.WeekOf' is not a valid identifier.

  • Yeah, I missed a space before the as...

    AVG(CAST( ' + @SearchTerm + 'AS decimal))

    should be

    AVG(CAST( ' + @SearchTerm + ' AS decimal))

    To help us help you read this[/url]For better help with performance problems please read this[/url]

  • Yeah it was the space and the @sql was to be wrapped around a parenthesis. I did that and now it says it can't find the @startDate and @endDate.

    ALTER PROCEDURE SA_STPR_Reports_AverageSales

    @startDate datetime,

    @endDate datetime,

    @SearchTerm varchar(255)

    AS

    BEGIN

    DECLARE @SQL NVARCHAR(4000)

    SELeCT @sql = '

    SELECT u.FirstName + '' '' + u.LastName AS Name,

    s.WeekOf,

    AVG(CAST( ' + @SearchTerm + ' ' + 'AS decimal)) AS AvgSales

    FROM Sales s

    INNER JOIN User_Stores us ON us.StoreId = s.StoreId

    INNER JOIN Users u ON u.UserId = us.UserId

    INNER JOIN User_Roles ur ON ur.UserId = u.UserId

    WHERE s.WeekOf BETWEEN @startDate AND @endDate

    AND ' + @SearchTerm + ' IS NOT NULL

    AND ur.RoleId = 3

    Group BY u.FirstName, u.LastName, s.WeekOf'

    EXECUTE (@SQL)

    END

  • Oh right... silly me... Sorry I didn't test the syntax cause I didn't have any test data.

    The start and end dates will not be in the same scope as the rest of it... You'll need to add them by ending the string ' + @variable + ' continuing the string...

    Like with the other variable...

    One of the reasons why Dynamic SQL is kinda a pain in the arse...

    Another way to do this which may or may not work well in your environment might be to

    a) ditch the is null check in your where clause cause it's not affecting the results of your Avg statement. b) write a single select statement that calculates all of your averages and selects them all = to appropriately named variables (Again not sure how well this might perform) c) In an if Statement, associate the appropriate variable to your output parameter

    At least you wouldn't need to worry with recompiles and bad plans when the dynamic SQL changes in your proc that way...

    -Luke.

    To help us help you read this[/url]For better help with performance problems please read this[/url]

  • Thanks for the post Luke. I did try the other way to make this work. Though, it has turned out to be a long query, but I think I am okay with this for now. The performance would be okay since its looking for the average data, so this query won't return too many rows. I will try to update this in the future. Right now, it looks at what parameter(what field) was passed in, based on that it will grab the average of that field. So, if a dropdown has 12 fields, I have to write the same script 12 times the only difference was the field that was passed.

    This will work for now. Thanks for trying.

Viewing 8 posts - 1 through 7 (of 7 total)

You must be logged in to reply to this topic. Login to reply