查询计算具有良好性能的多列的百分比

时间:2015-04-07 07:24:15

标签: sql-server performance percentage query-performance

我有一些表格如下:

[myCategory]                      [mySales]
+------+---------+               +------------+-----+--------+-------+
| id   | name    |               | date       | cat | price  | code  |
+------+---------+               +------------+-----+--------+-------+
| 1    | cat1    |               | 2015/01/01 | 1   | 25000  | 2     |
| 2    | cat2    |               | 2015/01/01 | 2   | 32000  | 4     |
| 3    | cat3    |               | 2015/02/01 | 1   | 25000  | 6     |
| 4    | cat4    |               | 2015/02/01 | 3   | 40000  | 4     |
: ..   : ...     :               : ...        : ..  :        : ..    :
+------+---------+               +------------+-----+--------+-------+
   \---------------- Foreign Key ----------------/

我想得到这个结果:

[results are between @fromDate and @toDate]
+------+-----------+-----------+-------------+---------------+-...-+
| code | totalSale | prcntSale | ttlSaleCat1 | prcntSaleCat1 | ... |
+------+-----------+-----------+-------------+---------------+-...-+
| 2    | 25000     | 20        | 25000       | 50            | ... |
| 4    | 72000     | 60        | 0           | 0             | ... |
| 6    | 25000     | 20        | 25000       | 50            | ... |
: ..   : ...       : ..        : ...         : ..            : ... :
+------+-----------+-----------+-------------+---------------+-...-+
  

我的问题在于计算百分比。

现在我已经在每个类别的存储过程中声明了一些变量并收集了每个ttlSaleN列的总数,然后在主查询中使用它们,我的解决方案应该变得更快,我想我应该更改我的溶液

我的查询类似于:

Declare @totalSale money = (select sum(s.price) 
                           from mySales s 
                           where s.date Between @fromDate and @toDate)
Declare @ttlSale1 money = (select sum(s.price) 
                           from mySales s 
                           where s.date Between @fromDate and @toDate and s.cat = 1)
...
select s.code, sum(s.price) as totalSale, sum(s.price) * 100 / @totalSale as prcntSale
               sum(case s.cat when 1 then s.price else 0 end) as ttlSaleCat1, sum(case s.cat when 1 then s.price else 0 end) * 100 / @ttlSale1 as prcntSaleCat1
from mySales s
where s.date Between @fromDate and @toDate
group by s.code

所有这些数据都是我刚才写的那些样本,如果有任何问题请忽略它们;)。

我认为对所有计算使用单个查询可以使其更快 - 删除变量 - ,如果我的方式错误,请指导我正确的方式。

1 个答案:

答案 0 :(得分:1)

对不起,与我通常写的相比,这真的很糟糕,但我匆匆忙忙。我建议尝试这样的事情:

declare @myCategory as table(id int, name varchar(10))
declare @mySales as table(date datetime, cat int, price float, code int)
declare @fromDate as datetime = '2015-01-01'
declare @toDate as datetime = '2015-02-02'

insert into @myCategory
values
     (1, 'Cat1')
    ,(2, 'Cat2')
    ,(3, 'Cat3')
    ,(4, 'Cat4')
insert into @mySales
values
     ('2015-01-01', 1, 25000, 2)
    ,('2015-01-01', 2, 32000, 4)
    ,('2015-02-01', 1, 25000, 6)
    ,('2015-02-01', 3, 40000, 4)


SELECT      S.code, sum(totalSale) as totalSale, sum(totalSale) * 100/prcntSale as prcntSales,
            sum(ttlSaleCat1) as ttlSaleCat1, sum(ttlSaleCat1) * 100/prcntSaleCat1 as prcntSaleCat1
FROM
    (
    select      s.code,
                s.price as totalSale,
                sum(s.price) over(partition by 1) as prcntSale,
                case s.cat when 1 then s.price else 0 end as ttlSaleCat1,
                sum(case when s.cat = 1 then SUM(s.price) end) over(partition by 1) as prcntSaleCat1
    from        @mySales s
    where       s.date Between @fromDate and @toDate
    group by    s.code, PRICE, CAT
    ) AS S
group by    s.code, prcntSale, prcntSaleCat1