View not running - percentile_cont

北城余情 提交于 2021-02-11 13:33:01

问题


I have the following code:

SELECT  DISTINCT
        SQ.COMP_ID,
        SQ.JT,
        CAST(MIN(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT)  AS DECIMAL (10,2)) AS MINIMUM,
        CAST(PERCENTILE_CONT(0.15) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P15,
        CAST(PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P25,
        CAST(AVG(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS AVERAGE,
        CAST(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS MEDIAN,  
        CAST(PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P75,
        CAST(PERCENTILE_CONT(0.85) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P85,
        CAST(MAX(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS MAXIMUM,
        COUNT(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS AMOUNT,
        SQ.TARGET_DATE
FROM
(
SELECT  DISTINCT
        E.COMP_ID, 
        E.STAFF_ID, 
        E.CONTRACT_ID,
        CT.JOB_TITLE AS JT, 
        CAST(SUM(E.REVENUE) AS DECIMAL (10,2)) AS SUM_SALES,
        DT.CAL_DATE AS TARGET_DATE

FROM SALES E
LEFT JOIN DATES_TABLE DT ON 1=1
LEFT JOIN CONTRACT_TABLE CT ON CT.COMP_ID = E.COMP_ID and CT.STAFF_ID = E.STAFF_ID AND CT.CONTRACT_ID = E.CONTRACT_ID
LEFT JOIN J_CONDI C3 ON E.COMP_ID = C3.COMP_ID AND C3.COND_DATE = '20200101'

WHERE 
    E.SALES_DATE = DATEADD(MM,DATEDIFF(MM,0,DT.CAL_DATE),0) 
AND E.SALES_ID in ('566165', '864651')

GROUP BY
        E.COMP_ID, 
        E.STAFF_ID, 
        E.CONTRACT_ID,
        CT.JOB_TITLE,   
        DT.CAL_DATE
) SQ
WHERE
SQ.COMP_ID = '1561656' AND
SQ.TARGET_DATE = '20201215'

if I run the code as a select statement with the where clause then it runs and performs very well!

but if I create a query:

CREATE VIEW SALES_STATS AS
(
SELECT  DISTINCT
        SQ.COMP_ID,
        SQ.JT,
        CAST(MIN(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT)  AS DECIMAL (10,2)) AS MINIMUM,
        CAST(PERCENTILE_CONT(0.15) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P15,
        CAST(PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P25,
        CAST(AVG(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS AVERAGE,
        CAST(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS MEDIAN,  
        CAST(PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P75,
        CAST(PERCENTILE_CONT(0.85) WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS P85,
        CAST(MAX(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS DECIMAL (10,2)) AS MAXIMUM,
        COUNT(SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) AS AMOUNT,
        SQ.TARGET_DATE
FROM
(
SELECT  DISTINCT
        E.COMP_ID, 
        E.STAFF_ID, 
        E.CONTRACT_ID,
        CT.JOB_TITLE AS JT, 
        CAST(SUM(E.REVENUE) AS DECIMAL (10,2)) AS SUM_SALES,
        DT.CAL_DATE AS TARGET_DATE

FROM SALES E
LEFT JOIN DATES_TABLE DT ON 1=1
LEFT JOIN CONTRACT_TABLE CT ON CT.COMP_ID = E.COMP_ID and CT.STAFF_ID = E.STAFF_ID AND CT.CONTRACT_ID = E.CONTRACT_ID
LEFT JOIN J_CONDI C3 ON E.COMP_ID = C3.COMP_ID AND C3.COND_DATE = '20200101'

WHERE 
    E.SALES_DATE = DATEADD(MM,DATEDIFF(MM,0,DT.CAL_DATE),0) 
AND E.SALES_ID in ('566165', '864651')

GROUP BY
        E.COMP_ID, 
        E.STAFF_ID, 
        E.CONTRACT_ID,
        CT.JOB_TITLE,   
        DT.CAL_DATE
) SQ
)

And I call the view as follows

SELECT *
FROM SALES_STATS SST
WHERE
SST.COMP_ID = '1561656' AND
SST.TARGET_DATE = '20201215'

Then it runs and runs and runs and runs and runs and runs and runs and runs and runs and runs and runs and runs... it outputs no result

My colleague told me it could be because of WITHIN GROUP (ORDER BY SQ.SUM_SALES) OVER (PARTITION BY SQ.JT) but he doesn't know how to solve it

Is there another way to get the PERCENTILEs without using PERCENTILE_CONT(x) or without any function which uses OVER (PARTITION BY)

I just want to have the stats like min max median and percentiles

Or can I for the subquery to execute first? I have also tried using top(51619861) max number but it doesn't work.


回答1:


This is a bit long for a comment.

SQL Server has an alternative to views which are user defined functions. In particular, you can have a UDF that does all the following:

  • It takes parameters.
  • It returns a table.
  • It is inlined like a view (that is, the "code" is essentially inserted into the query, but it is a little more complicated than that).

I think of them as "parameterized views".

My suggestion is that you create a user defined table-valued inline function that takes the parameters that you would put in the WHERE clause.

The basic syntax in your case is:

CREATE FUNCTION ufn_sales_stats (
    @compid int,
    @target_date date
)  RETURNS TABLE  
AS  
RETURN (  <your parameterized query here> );


来源:https://stackoverflow.com/questions/65421903/view-not-running-percentile-cont

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!