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

时间:2017-01-10 14:19:22

标签: sql sql-server-2008

首先,为我的标题含糊不清道歉,一旦我对我需要做的事情有了更好的理解,我就会编辑它。希望这个问题更具启发性。

考虑一个看起来像这样的集合;

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

我想要一个返回此选项的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

结果中的值是每个月每个水果的百分比和所有月份的总数。例如。第一个结果(90.9%)表明1月份所有水果的90.9%是苹果((1月的总苹果/ 1月的总水果)* 100)

我已经成功写了一个返回第一列和最后一列的select语句,我遇到的问题是中间三列,以及如何获得每个月的每个水果的百分比。

显然,这是一个虚假的设置,我试图在真实数据"月"中试图简化我的问题。实际上是一个DateTime,可以是任何日期。我不关心水果在结果中出现的顺序,也不担心百分比中的(小)舍入误差。

5 个答案:

答案 0 :(得分:3)

窗口与条件聚合

协同工作
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

返回

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

答案 1 :(得分:2)

使用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;

以下是我得到的输出,

enter image description here

希望这会帮助你。

答案 2 :(得分:1)

条件总和可能是你的答案。你仍然有问题要弄清楚要处理哪个月,但这并不算太糟糕。

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

答案 3 :(得分:1)

您可以每月总计数量,添加总数,然后将它们按行

进行转动
;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

输出:

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

答案 4 :(得分:1)

虽然已有一个已接受的答案,但我想尝试使用汇总/多维数据集,以便找到一种优雅的方式来预先汇总每月所需的总和,水果和总数:

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

查询还可以处理数据条目的数据集,其中数量条目为特​​定月份或完整月份的水果的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