为另一列的不同范围计算列的中位数(架上天数)(价格)

时间:2017-12-18 19:58:40

标签: sql-server

我正在努力寻找一年中每一天的中位数克拉黄金。我需要根据不同栏目中的黄金价格范围来隔离这些。

数据:

Create table Daily_Gold_Rate
( S_No int, Dt datetime, Carat int, Gold_Rate numeric(18,2))

Insert into Daily_Gold_Rate values(1,'2013-01-03',18,155.00)
Insert into Daily_Gold_Rate values(2,'2013-01-03',22,190.50)
Insert into Daily_Gold_Rate values(3,'2013-01-03',24,202.23)
Insert into Daily_Gold_Rate values(4,'2013-01-03',18,400.00)
Insert into Daily_Gold_Rate values(5,'2013-01-03',22,480.50)
Insert into Daily_Gold_Rate values(6,'2013-01-03',24,671.23)

Insert into Daily_Gold_Rate values(7,'2013-01-04',18,153.00)
Insert into Daily_Gold_Rate values(8,'2013-01-04',22,191.00)
Insert into Daily_Gold_Rate values(9,'2013-01-04',24,202.25)
Insert into Daily_Gold_Rate values(10,'2013-01-04',18,351.00)
Insert into Daily_Gold_Rate values(11,'2013-01-04',22,892.00)
Insert into Daily_Gold_Rate values(12,'2013-01-04',24,1003.25)

Insert into Daily_Gold_Rate values(13,'2013-01-05',18,150.00)
Insert into Daily_Gold_Rate values(14,'2013-01-05',22,190.00)
Insert into Daily_Gold_Rate values(15,'2013-01-05',24,203.25)
Insert into Daily_Gold_Rate values(16,'2013-01-05',18,773.00)
Insert into Daily_Gold_Rate values(17,'2013-01-05',22,542.00)
Insert into Daily_Gold_Rate values(18,'2013-01-05',24,182.25)

Insert into Daily_Gold_Rate values(19,'2013-01-06',18,158.00)
Insert into Daily_Gold_Rate values(20,'2013-01-06',22,189.50)
Insert into Daily_Gold_Rate values(21,'2013-01-06',24,201.50)
Insert into Daily_Gold_Rate values(22,'2013-01-06',18,624.00)
Insert into Daily_Gold_Rate values(23,'2013-01-06',
Insert into Daily_Gold_Rate values(24,'2013-01-06',24,411.50)

简单的PERCENTILE_CONT如下所示:

Select Dt, Carat, Gold_Rate, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY 
Carat) OVER (PARTITION BY Carat) AS MedianCont
from Daily_Gold_Rate
order by Dt;Expected output is like this:

返回此数据:

Dt            | Carat | Gold_Rate | MedianCont
2013-01-03 00:00:00.000 | 18 | 155.00 | 18
2013-01-03 00:00:00.000 | 18 | 400.00 | 18
2013-01-03 00:00:00.000 | 22 | 480.50 | 22
2013-01-03 00:00:00.000 | 22 | 190.50 | 22
2013-01-03 00:00:00.000 | 24 | 202.23 | 24
2013-01-03 00:00:00.000 | 24 | 671.23 | 24
2013-01-04 00:00:00.000 | 24 | 202.25 | 24
2013-01-04 00:00:00.000 | 24 | 1003.25 | 24
2013-01-04 00:00:00.000 | 18 | 153.00 | 18
2013-01-04 00:00:00.000 | 18 | 351.00 | 18
2013-01-04 00:00:00.000 | 22 | 892.00 | 22
2013-01-04 00:00:00.000 | 22 | 191.00 | 22
2013-01-05 00:00:00.000 | 22 | 542.00 | 22
2013-01-05 00:00:00.000 | 22 | 190.00 | 22
2013-01-05 00:00:00.000 | 18 | 150.00 | 18
2013-01-05 00:00:00.000 | 18 | 773.00 | 18
2013-01-05 00:00:00.000 | 24 | 203.25 | 24
2013-01-05 00:00:00.000 | 24 | 182.25 | 24
2013-01-06 00:00:00.000 | 24 | 201.50 | 24
2013-01-06 00:00:00.000 | 24 | 411.50 | 24
2013-01-06 00:00:00.000 | 18 | 158.00 | 18
2013-01-06 00:00:00.000 | 18 | 624.00 | 18
2013-01-06 00:00:00.000 | 22 | 735.50 | 22
2013-01-06 00:00:00.000 | 22 | 189.50 | 22

我需要关注黄金价格范围。所以,我正在尝试通过这个查询:

with a as (
    select year(Dt) as "year", month(Dt) as "month", day(Dt) as "day",
    case when Gold_Rate / 200 < 5 then Gold_Rate / 200 else 5 end as 
price_bucket,
    PERCENTILE_CONT(.50) WITHIN GROUP (ORDER BY Carat) over (PARTITION BY 
day(Dt), month(Dt)) as MED_days
from Daily_Gold_Rate
group by year(Dt), month(Dt), day(Dt), Gold_Rate / 200, Carat)
select "year", "month", "day",
[1] as "less than 400", [2] as "400-599", [3] as "600-799", [4] as "800-
999", [5] as "Over 1000"
from a pivot (max(MED_days) for price_bucket in ([1], [2], [3], [4], [5])) p
order by "year", "month", "day";

但是,这就是我所得到的。 :(

Year | Month | Day | 1-399 | 400-599 | 600-799| 800-999| Over 1000
2013 | 1     | 3   | NULL  | 22      | NULL   | NULL   | NULL
2013 | 1     | 4   | NULL  | NULL    | NULL   | NULL   | 22
2013 | 1     | 5   | NULL  | NULL    | NULL   | NULL   | NULL
2013 | 1     | 6   | NULL  | NULL    | NULL   | NULL   | NULL

1 个答案:

答案 0 :(得分:1)

在百分位计算之前进行透视:

select distinct
      dt
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratelt400)      OVER (PARTITION BY dt) ratelt400
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratebtwn400599) OVER (PARTITION BY dt) ratebtwn400599
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratebtwn600799) OVER (PARTITION BY dt) ratebtwn600799
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratebtwn800999) OVER (PARTITION BY dt) ratebtwn800999
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rateovr1000)    OVER (PARTITION BY dt) rateovr1000
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratlt400)      OVER (PARTITION BY dt) caratlt400
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratbtwn400599) OVER (PARTITION BY dt) caratbtwn400599
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratbtwn600799) OVER (PARTITION BY dt) caratbtwn600799
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratbtwn800999) OVER (PARTITION BY dt) caratbtwn800999
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratovr1000)    OVER (PARTITION BY dt) caratovr1000
from (
SELECT
      DATEADD(day, DATEDIFF(day, 0, dt), 0) dt
    , CASE WHEN Gold_Rate < 400               THEN Gold_Rate END ratelt400
    , CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN Gold_Rate END ratebtwn400599
    , CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN Gold_Rate END ratebtwn600799
    , CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN Gold_Rate END ratebtwn800999
    , CASE WHEN Gold_Rate >= 1000             THEN Gold_Rate END rateovr1000
    , CASE WHEN Gold_Rate < 400               THEN carat END caratlt400
    , CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN carat END caratbtwn400599
    , CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN carat END caratbtwn600799
    , CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN carat END caratbtwn800999
    , CASE WHEN Gold_Rate >= 1000             THEN carat END caratovr1000
FROM Daily_Gold_Rate
) d
GO
dt                  | ratelt400 | ratebtwn400599 | ratebtwn600799 | ratebtwn800999 | rateovr1000 | caratlt400 | caratbtwn400599 | caratbtwn600799 | caratbtwn800999 | caratovr1000
:------------------ | --------: | -------------: | -------------: | -------------: | ----------: | ---------: | --------------: | --------------: | --------------: | -----------:
03/01/2013 00:00:00 |     190.5 |         440.25 |         671.23 |           null |        null |         22 |              20 |              24 |            null |         null
04/01/2013 00:00:00 |   196.625 |           null |           null |            892 |     1003.25 |         20 |            null |            null |              22 |           24
05/01/2013 00:00:00 |   186.125 |            542 |            773 |           null |        null |         23 |              22 |              18 |            null |         null
06/01/2013 00:00:00 |     189.5 |          411.5 |            624 |           null |        null |         22 |              24 |              18 |            null |         null

dbfiddle here

下面是一些按克拉或率计算的值的工作查询:

修订回答:

按天计算费率

SELECT DISTINCT
      DATEADD(day, DATEDIFF(day, 0, dt), 0) dt
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate < 400               THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) lt400
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn400599
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn600799
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn800999
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate >= 1000             THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) ovr1000
FROM Daily_Gold_Rate

GO
dt                  |   lt400 | btwn400599 | btwn600799 | btwn800999 | ovr1000
:------------------ | ------: | ---------: | ---------: | ---------: | ------:
03/01/2013 00:00:00 |   190.5 |     440.25 |     671.23 |       null |    null
04/01/2013 00:00:00 | 196.625 |       null |       null |        892 | 1003.25
05/01/2013 00:00:00 | 186.125 |        542 |        773 |       null |    null
06/01/2013 00:00:00 |   189.5 |      411.5 |        624 |       null |    null

按天克拉

SELECT DISTINCT
      DATEADD(day, DATEDIFF(day, 0, dt), 0) dt
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate < 400               THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) lt400
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn400599
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn600799
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn800999
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate >= 1000             THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) ovr1000
FROM Daily_Gold_Rate
GO
dt                  | lt400 | btwn400599 | btwn600799 | btwn800999 | ovr1000
:------------------ | ----: | ---------: | ---------: | ---------: | ------:
03/01/2013 00:00:00 |    22 |         20 |         24 |       null |    null
04/01/2013 00:00:00 |    20 |       null |       null |         22 |      24
05/01/2013 00:00:00 |    23 |         22 |         18 |       null |    null
06/01/2013 00:00:00 |    22 |         24 |         18 |       null |    null

dbfiddle here

按月:仅供参考

SELECT DISTINCT
      DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0) dt
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate < 400               THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) lt400
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) btwn400599
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) btwn600799
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) btwn800999
    , PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate >= 1000             THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) ovr1000
FROM Daily_Gold_Rate

GO
dt                  |  lt400 | btwn400599 | btwn600799 | btwn800999 | ovr1000
:------------------ | -----: | ---------: | ---------: | ---------: | ------:
01/01/2013 00:00:00 | 190.25 |        446 |     671.23 |        892 | 1003.25

dbfiddle here