计数函数中的SQL动态分区

时间:2017-08-29 12:31:05

标签: tsql sql-server-2014 sqlreportingservice

我有一个与报表服务一起使用的存储过程,并且报表有一些用户过滤器将值传递到存储过程。由于这些参数,显示内容的计数会发生变化,因此我希望在分区中使用它们来更改计数。我尝试了以下不起作用。

修改

计数在ss_number上完成,但不在@SearchBy上完成。所以,如果我有

SS#       |    Name    |    City  |  Amount

123456789 | Mike Smith | Trenton | 100.00

123456789 | Mike Smith | Trenton | 200.00

123456789 | Mike Smith | Jackson | 100.00

我的数量是3,即使@SearchBy = City,我正在过滤特伦顿。

CASE WHEN @SearchBy = 'Product Name' THEN count(ss_number) OVER (PARTITION BY ss_number, @SearchBy) 

现在我正在使用案例陈述,但它大大减慢了我的查询速度。

以下是没有case语句尝试在我的分区中使用该变量的代码。

CREATE PROCEDURE [dbo].[sp_My_sp]
@SearchBy VARCHAR(MAX), 
@SearchString VARCHAR(MAX),
@SearchNum Int,
@ClaimDate Datetime2

AS
WITH MyCTE AS
(   
SELECT val.Claim_date
, val.Claim_Status
, val.Status_Desc
, ES_Claim_Status
, val.ss_number
, val.name_field1
, val.street_add1
, val.street_add2
, val.city
, val.state
, val.zip_code_pre
, val.reference_number
, val.Game_Name 
, val.val_agent
, val.home_number
, val.work_phone
, val.county_desc
, o.agent_num
, count(ss_number) OVER (PARTITION BY ss_number, @SearchBy) as count
, prize_amount
FROM Sec_Claims val left outer join vw_owners_concat_agent_num o
ON val.SS_NUMBER = convert(varchar(15),o.SS_NO)
where convert(numeric,prize_amount) >= 600)
SELECT Claim_date
, CASE WHEN agent_num IS NULL THEN 'NO' ELSE 'YES' END as "IsRetailer"
, Claim_Status
, Status_Desc
, ES_Claim_Status
, ss_number
, name_field1
, street_add1
, street_add2
, city
, state
, zip_code_pre
, reference_number
, Game_Name 
, val_agent
, home_number
, work_phone
, county_desc
, agent_num
, count
, ROW_NUMBER() OVER(PARTITION BY Name_Field1 ORDER BY Name_Field1) As RowNumber
, convert(decimal(10,2),prize_amount) as prize_amount
, sum(Convert(decimal(9,2),prize_amount)) OVER (PARTITION BY ss_number, Name_Field1) AS prizesum
FROM MyCTE 
WHERE 
    (CASE
        WHEN @SearchBy = 'Agent Number' THEN agent_num
        WHEN @SearchBy = 'SS#' THEN SS_NUMBER
        WHEN @SearchBy = 'Name' THEN Name_Field1
        WHEN @SearchBy = 'Address' THEN STREET_ADD1
        WHEN @SearchBy = 'City' THEN City
        WHEN @SearchBy = 'Claim#' THEN convert(varchar(max),REFERENCE_NUMBER)
        WHEN @SearchBy = 'Validating Retailer' THEN convert(varchar(max),VAL_AGENT)
        WHEN @SearchBy = 'County' THEN COUNTY_DESC
        WHEN @SearchBy = 'Home Phone' THEN convert(varchar(max),HOME_NUMBER)
        WHEN @SearchBy = 'Work Phone' THEN convert(varchar(max),WORK_PHONE)
        WHEN @SearchBy = 'Game Name' THEN GAME_NAME
    END 
    like (@SearchString))
    and
    count>= @SearchNum 
    and
    claim_date > @ClaimDate 
ORDER BY ss_number

3 个答案:

答案 0 :(得分:0)


您的查询正在变慢,因为您可以想象,需要针对每一行评估“case”语句,使用Select语句。
这意味着如果您的查询加载了很多行,则会增加很多开销。
 
我看到两种不同的方法来解决您的问题。我不喜欢他们中的任何一个,但他们的作品:)左

第一个解决方案
使用IF ... ELSE来涵盖所有可能的输入。 这意味着您必须多次编写相同的查询,以便在一行代码中区分它。
这意味着代码变得冗长而且基本上不可维护

第二个解决方案
构建动态查询。
你可以写这样的东西

VisualStudio-Emulation

答案 1 :(得分:0)

尝试使用"案例"在Over声明中:

Declare @SearchBy varchar(255)
SET @SearchBy = 'Product Name'

Select count(ss_number)
            OVER (PARTITION BY ss_number,
                               Case @SearchBy
                                    When 'Product Name' then [Name]
                                    When 'City Name'    then [City]
                                    When 'Product Name' then cast([Amount] as varchar(255))
                               END) t     
    from (VALUES (123456789,'Mike Smith','Trenton',100.00)
                ,(123456789,'Mike Smith','Trenton',200.00)
                ,(123456789,'Mike Smith','Jackson',100.00)
         ) as t([ss_number],Name,City,Amount)

答案 2 :(得分:0)

根据您的需求判断,您首先需要动态SQL。话虽如此,您可以使用row_number()。我仍然不了解您的额外分区,但您可以将其添加到下面的示例中。您可以运行它,它将打印出将要执行的命令。

--create procedure yourProc(
--                          @SearchBY varchar(64)           --Column to search / filter by
--                          ,@SearchString varchar(256)     --Values to limit column above by
--                          ,@Count int                     --limit the count per each SSN
--                          ,@Date datetime)                
--as

--begin

declare     @SearchBY varchar(64)       = 'City'            --Column to search / filter by
declare     @SearchString varchar(256)  = 'Trenton'         --Values to limit column above by
declare     @Count int                  = 3                 --limit the count per each SSN
declare     @Date datetime              = '12/25/2017'

declare @SQL nvarchar(max) = 

'with cte as(
    select
        ss_number
        ,Name
        ,City
        ,Amount
        ,row_number() over (partition by ss_number order by (select 1)) as RN
    from
        YourTable
    where
        SomeDateColumn >= ''' + convert(varchar(10),@Date,112) +
        ''' and ' + @SearchBY + ' = ''' + @SearchString +
        ''')
 select *
 from cte
 where ss_number in 
 (select distinct ss_number from cte where RN >= ' + cast(@Count as varchar(16)) + ')
 '

print(@SQL)
--exec(@SQL)
--end

以下是一个工作示例:http://rextester.com/BPWOXH7777