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

Posted

技术标签:

【中文标题】用于计算具有良好性能的许多列的百分比的查询【英文标题】:Query for calculationg percentage of many columns with a good performance 【发布时间】:2015-04-07 07:24:14 【问题描述】:

我有一些表格,如下例所示:

[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

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

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

【问题讨论】:

有点不清楚。你在做单一陈述时有什么问题吗?如果不是,那么只需进行另一个查询并进行比较。如果不在您的生产中运行这两个查询,我们怎么能假设某些查询比其他查询更好? @GiorgiNakeuri 我将删除那些计算总和值以计算百分比的变量。 这是非常基本的原始查询。我认为您最好通过索引和统计信息进行优化,而不是通过优化该查询。 【参考方案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

【讨论】:

以上是关于用于计算具有良好性能的许多列的百分比的查询的主要内容,如果未能解决你的问题,请参考以下文章

基于 2 列的组合添加百分比列(Postgresql)

计算布尔列的百分比

性能报告 - 两个百分比列是啥

来自有条件和无条件列的 SQL 查询分组的比率或百分比

使用 GROUP BY 查询计算百分比

用于执行聚合和计算百分比的 SQL 查询