简体   繁体   English

如何在SQL中编写select语句,以从提供的集合中返回以下结果

[英]How to write a select statement in SQL that returns the following result from the set provided

Firstly, apologies for the vagueness of my title, I will edit it once I have a better understanding of what I need to do. 首先,为标题的模糊性表示歉意,一旦我对需要做的事情有了更好的了解,我将对其进行编辑。 Hopefully the question is a bit more revealing. 希望这个问题能揭示更多。

Consider a set that looks like this; 考虑一个看起来像这样的集合。

Fruit | Quantity | Month
-------------------------
Apple |    5     | Jan
Pear  |    2     | May
Orange|    1     | Jan
Apple |    10    | May
Pear  |    2     | May
Orange|    1     | Jul
Apple |    5     | Jan
Pear  |    2     | Jul
Orange|    1     | Jul

I would like a select statement that returns this; 我想要一条返回此内容的select语句;

Fruit | Jan % | May % | Jul % | Total %
---------------------------------------
Apple | 90.9  | 71.43 | 0     | 68.97
Pear  | 0     | 28.57 | 50    | 20.69
Orange| 9.1   | 0     | 50    | 10.34

The values in the results are the percentages of each fruit for each month and the total for all months. 结果中的值是每个月每个水果的百分比和所有月总计的百分比。 Eg the first result (90.9%) is stating that 90.9% of all fruit for January were apples ((Total apples for Jan / Total fruit for Jan) * 100) 例如,第一个结果(90.9%)表示一月份所有水果中有90.9%是苹果((一月总苹果/一月总水果)* 100)

I have successfully written a select statement that returns the first and last columns, the trouble I'm having is with the middle three columns and how to get the percentages of each fruit for each month. 我已经成功地编写了一条select语句,该语句返回第一列和最后一列,而我遇到的麻烦是中间的三列以及如何获取每个月每个水果的百分比。

Obviously this is a fake set that I contrived to try to simplify my problem, in the real data "month" is actually a DateTime and can be any date. 显然,这是我为简化问题而设计的伪集,在实际数据中,“ month”实际上是DateTime,可以是任何日期。 I do not care what order the fruit appear in the results, nor am I worried about (small) rounding errors in the percentages. 我不在乎结果显示水果的顺序,也不担心百分比的(小)舍入误差。

The window functions in concert with aa conditional aggregation 窗口与条件聚集协同工作

Declare @YourTable table (Fruit varchar(25),Quantity  int, Month varchar(25))
Insert Into @YourTable values
('Apple',5,'Jan'),
('Pear',2,'May'),
('Orange',1,'Jan'),
('Apple',10,'May'),
('Pear',2,'May'),
('Orange',1,'Jul'),
('Apple',5,'Jan'),
('Pear',2,'Jul'),
('Orange',1,'Jul')

Select Fruit
      ,Jan   = max(case when Month='Jan' then value else 0 end)
      ,May   = max(case when Month='May' then value else 0 end)
      ,Jul   = max(case when Month='Jul' then value else 0 end)
      ,Total = max(Total)
 From  (
            Select Distinct Fruit
                  ,Month
                  ,Value = sum(Quantity*100.0) over (Partition By Fruit,Month) / sum(Quantity) over (Partition By Month)
                  ,Total = sum(Quantity*100.0) over (Partition By Fruit) / sum(Quantity) over ()
             From  @YourTable
        ) A
 Group By Fruit

Returns 退货

Fruit   Jan         May         Jul         Total
Apple   90.909090   71.428571   0.000000    68.965517
Orange  9.090909    0.000000    50.000000   10.344827
Pear    0.000000    28.571428   50.000000   20.689655

This can be done easier with versions from 2012, but you are using 2008. Hence you can make use of the below query which seems to be quiet complicated 使用2012年以后的版本可以更轻松地完成此操作,但是您使用的是2008年。因此,您可以使用以下查询,看起来似乎很安静

WITH totalData AS 
    (SELECT Month, SUM(Quantity) totalpermonth 
    FROM fruitsData 
    GROUP BY Month), -- Calculating the total fruits per month

totalFriutData as 
    (SELECT Sum(Quantity) totalFruit 
    FROM fruitsData) -- Calculating the total fruits


SELECT Fruit, Jan, May, Jul, CAST(totalperfruit*100 AS decimal)/tf.totalFruit as Total
FROM(
    SELECT Fruit, SUM(CASE WHEN Month = 'Jan' THEN percentage_value ELSE 0 END) Jan
    , SUM(CASE WHEN Month = 'May' THEN percentage_value ELSE 0 END) May
    , SUM(CASE WHEN Month = 'Jul' THEN percentage_value ELSE 0 END) Jul
    , SUM(totalperfruit) totalperfruit
    FROM(
        SELECT Fruit, CAST(SUM(Quantity)*100 AS decimal)/td.totalpermonth percentage_value, fd.Month, td.totalpermonth, SUM(Quantity) totalperfruit
        FROM fruitsData fd
        LEFT JOIN totalData td on fd.Month = td.Month
        GROUP BY Fruit, fd.Month, td.totalpermonth)t1
    GROUP BY Fruit
) t1
CROSS JOIN totalFriutData tf;

Below is the output I got, 以下是我得到的输出,

在此处输入图片说明

Hope this would help you out. 希望这对您有所帮助。

Conditional sums might be your answer. 有条件的和可能是您的答案。 You still have the problem of figuring out which months to process, but that's not too bad. 您仍然有一个问题要弄清要处理的月份,但这还不错。

SELECT
    SUM(CASE WHEN MONTH(SalesDate) = 1 THEN 1 ELSE 0 END)*100.0/(SELECT COUNT(*) FROM SALES WHERE SalesDate BETWEEN @Start and @End) as JAN
    SUM(CASE WHEN MONTH(SalesDate) = 2 THEN 1 ELSE 0 END)*100.0/(SELECT COUNT(*) FROM SALES WHERE SalesDate BETWEEN @Start and @End) as FEB
FROM
    FruitSales

You can sum quantities per month, add total and then pivot them in line 您可以每月汇总数量,添加总计,然后按顺序进行排列

;with
m as (
    select fruit, Quantity, DATEPART(mm,dt) mm from d
),
tt as (
    select sum(Quantity)*1.0 TotalQt from m
),
tf as (
    select fruit, sum(Quantity)*1.0 TotalQtFr from m group by fruit
),

tm as (
    select mm, sum(Quantity)*1.0 TotalQtMM
    from m 
    group by mm
),
d2 as (
    select m.Fruit, m.mm, cast(100*Quantity/tm.TotalQtMM as decimal(5,2)) QuantityPerc
    from m
    join tm on m.mm=tm.mm
    union all
    select tf.Fruit, 13, cast(100*TotalQtFr/TotalQt as decimal(5,2)) QuantityPerc
    from tf 
    cross join tt
),
p as (
    select *
    from d2
    pivot (sum(QuantityPerc) for mm in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13])) p
)
-- select * -- to see all months
select [Fruit], Isnull([1], 0) [Jan %], Isnull([5], 0) [May %], Isnull([7], 0) [Jul %], Isnull([13], 0) [Total %]
from p
order by 1

The output: 输出:

Fruit   Jan %   May %   Jul %   Total %
Apple   90.90   71.43   0.00    68.97
Orange  9.09    0.00    50.00   10.34
Pear    0.00    28.58   50.00   20.69

Although there is already an accepted answer, I wanted to experiment with rollup/cube in order to find an elegant way of pre-aggregating the required sums per month, fruit and in total: 尽管已经有了一个可接受的答案,但我还是想对汇总/多维数据集进行试验,以便找到一种优雅的方式来预先汇总每月所需的总金额,水果和总计:

with groupedFruits as
      (select f.fruit, f.month, cast(CASE WHEN sum(quantity)=0 THEN NULL else sum(quantity) END as decimal) as quantity
      from fruits f
      group by f.month, f.fruit with cube)
select f2.fruit,
  (select g.quantity from groupedFruits g where f2.fruit = g.fruit and g.month='Jan') /
  (select g.quantity from groupedFruits g where g.fruit is null and g.month='Jan') as jan,
  (select g.quantity from groupedFruits g where f2.fruit = g.fruit and g.month='May') /
  (select g.quantity from groupedFruits g where g.fruit is null and g.month='May') as may, 
  (select g.quantity from groupedFruits g where f2.fruit = g.fruit and g.month='Jul') /
  (select g.quantity from groupedFruits g where g.fruit is null and g.month='Jul') as jul,
  (select g.quantity from groupedFruits g where f2.fruit = g.fruit and g.month='Aug') /
  (select g.quantity from groupedFruits g where g.fruit is null and g.month='Aug') as aug,
  (select g.quantity from groupedFruits g where f2.fruit = g.fruit and g.month='Sep') /
  (select g.quantity from groupedFruits g where g.fruit is null and g.month='Sep') as sep,
  sum(f2.quantity) / (select g.quantity from groupedFruits g where g.fruit is null and g.month is null) as total
from fruits f2
group by f2.fruit

The query can also handle data sets where quantity entries are 0 either for a fruit in a specific month or for a complete month, eg when entering tuples like ('Orange', 0, 'Aug') and ('Kiwi', 0, 'Sep') , which then yields: 该查询还可以处理数据集,其中特定月份或整个月份的水果的数量条目为0 ,例如,输入('Orange', 0, 'Aug')('Kiwi', 0, 'Sep') ,则产生:

fruit   |jan    |may    |jul    |aug    |sep    |total
--------|-------|-------|-------|-------|-------|-----
Apple   |0,91   |0,71   |NULL   |NULL   |NULL   |0,69
Kiwi    |NULL   |NULL   |NULL   |NULL   |NULL   |0,00
Orange  |0,09   |NULL   |0,50   |NULL   |NULL   |0,10
Pear    |NULL   |0,29   |0,50   |NULL   |NULL   |0,21

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM