问题
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