按年份枢纽累积总数,然后选择前5名

时间:2019-03-26 10:33:41

标签: sql sql-server pivot

我正在尝试获取一些年份的数据,以便随着年份的增加累计给我,然后获得前5名。

我尝试使用“年”列中的年份总计中的总和,但似乎没有增加。我认为该问题可能是由于某些空值引起的吗?

表中的数据当前显示为

Name | ApplesEaten | Year
Bob  |      2      | 2012
Bob  |      5      | 2016
Elvis|      1      | 2017
Elvis|      2      | 2012
Sam  |      8      | 2008
Elvis|      6      | 2004
Sam  |      24     | 2019
Sarah|      14     | 2015
Bob  |      6      | 2005
Rachel|      12     | 2010
Rachel|      10     | 2008
Bob  |      82     | 2006

但是我的目标是像

Name| 2004 | 2005 | 2006 ..... 
Bob |   0  |  6   |  88

下一个问题是在完成枢纽操作后获得前5名!

3 个答案:

答案 0 :(得分:1)

这是您想要的吗?

select top (5) name,
       sum(case when year <= 2005 then ApplesEaten else 0 end) as apples_2005,
       sum(case when year <= 2006 then ApplesEaten else 0 end) as apples_2006,
       . . .
       sum(case when year <= 2019 then ApplesEaten else 0 end) as apples_2019
from t
group by name
order by sum(ApplesEaten) desc

答案 1 :(得分:1)

您可以在以下情况下使用大小写

#include <tuple>
#include <utility>
#include <iostream>

class Aa {
    public:
        Aa(int a1_, int a2_): a1(a1_), a2(a2_) {}

        template<std::size_t N>
        decltype(auto) get() const {
            if constexpr (N == 0) return a1;
            else if constexpr (N == 1) return a2;
        }

    private:
        int a1;
        int a2;
};

class Bb {
    public:
        Bb(Aa a_, int b_): a(a_), b(b_) {}

        template<std::size_t N>
        decltype(auto) get() const {
            if constexpr (N == 0) return a;
            else if constexpr (N == 1) return b;
        }

    private:
        Aa a;
        int b;
};


namespace std {
    // Aa
    template<>
    struct tuple_size<Aa> : std::integral_constant<std::size_t, 2> {};

    template<std::size_t N>
    struct tuple_element<N, Aa> {
        using type = decltype(std::declval<Aa>().get<N>());
    };

    // Bb
    template<>
    struct tuple_size<Bb> : std::integral_constant<std::size_t, 2> {};

    template<std::size_t N>
    struct tuple_element<N, Bb> {
        using type = decltype(std::declval<Bb>().get<N>());
    };
}

template
<typename T, typename tp_enabled = std::void_t<>>
constexpr bool is_tuple_like = false;

template
<typename T>
constexpr bool 
is_tuple_like
<
  T, 
  std::void_t
  <
    decltype(std::tuple_size<T>::value),
    decltype(std::declval<T&>().template get<std::size_t(0)>())
  >
> = true;

template<typename T>
auto encode(T const& t, std::ostream& os)->
std::enable_if_t<is_tuple_like<T>>
{
  encode_impl(t, os, std::make_index_sequence<std::tuple_size<T>::value>{ });
  os << std::endl;
}

template
<bool is_last, typename T>
auto
encode_one(T const& t, std::ostream& os)->
std::enable_if_t<!is_tuple_like<T>>
{
  os << t << (is_last ? " " : ", ");
}

template
<bool is_last, typename T>
auto
encode_one(T const& t, std::ostream& os)->
std::enable_if_t<is_tuple_like<T>>
{
  encode_impl(t, os, std::make_index_sequence<std::tuple_size<T>::value>{ });
  os << (is_last ? " " : ", ");
}

template
<typename T, std::size_t... I>
void encode_impl(T const& t, std::ostream& os, std::index_sequence<I...> const)
{
  constexpr auto last = sizeof...(I) - 1;
  os << "{ ";
  [[maybe_unused]] int const temp[] =
    { (encode_one<I == last>(t.template get<I>(), os), 0)... };
  os << "}";
}

int main () {
    auto a = Aa(1, 1);
    encode(a, std::cout);
    auto b = Bb(a, 1);
    encode(b, std::cout);
    return 0;
}

答案 2 :(得分:0)

样本数据

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE #Temp
;WITH CTE(Name , ApplesEaten , [Year])
AS
(
SELECT 'Bob'  ,  2      , 2012  UNION ALL
SELECT 'Bob'  ,  5      , 2016  UNION ALL
SELECT 'Elvis',  1      , 2017  UNION ALL
SELECT 'Elvis',  2      , 2012  UNION ALL
SELECT 'Sam'  ,  8      , 2008  UNION ALL
SELECT 'Elvis',  6      , 2004  UNION ALL
SELECT 'Sam'  ,  24     , 2019  UNION ALL
SELECT 'Sarah',  14     , 2015  UNION ALL
SELECT 'Bob'  ,  6      , 2005  UNION ALL
SELECT 'Rachel',  12     , 2010 UNION ALL
SELECT 'Rachel',  10     , 2008 UNION ALL
SELECT 'Bob'  ,   82     , 2006
)
SELECT Name , 
       ApplesEaten , 
       [Year]      
INTO #Temp
FROM CTE

使用动态Sql的Sql脚本

DECLARE @Columns nvarchar(max),
        @IsnullColumns nvarchar(max),
        @Sql  nvarchar(max)


SELECT @Columns = STUFF((SELECT DISTINCT ', '+QUOTENAME([Year])   FROM #Temp FOR XML PATH ('')),1,1,'')


 SELECT @IsnullColumns = STUFF((SELECT DISTINCT ', '+'ISNULL(MAX('+QUOTENAME([Year])+'),''0'') AS apples_' +CAST(([Year]) AS VARCHAR(20))
                            FROM #Temp FOR XML PATH ('')),1,1,'')

SET @Sql ='SELECT TOp 5 Name,'+@IsnullColumns+'
            FROM
            (
            SELECT *,SUM(ApplesEaten) OVER(PARTITION BY Name ORDER BY [Year]) AS SumApplesEaten FROM #Temp
            ) AS PVT
            PIVOT
            (
            MAX(SumApplesEaten) FOR [Year] IN ('+@Columns+')
            ) AS PVT
            GROUP BY Name
            ORDER BY Name'
PRINT @Sql
EXEC (@Sql)