按客户信息对子查询和组进行求和

时间:2009-05-12 11:46:56

标签: sql sql-server

我有三张桌子,如下所示:

Customer (CustomerID, AddressState)
Account (AccountID, CustomerID, OpenedDate)
Payment (AccountID, Amount)

付款表可以包含多个帐户付款,而客户可以有多个帐户。

我想要做的是按州和逐月检索所有付款的总额。 E.g。

Opened Date| State | Total
--------------------------
2009-01-01 |   CA  | 2,500
2009-01-01 |   GA  | 1,000
2009-01-01 |   NY  |   500
2009-02-01 |   CA  | 1,500
2009-02-01 |   NY  | 2,000

换句话说,我试图找出每个国家每个月付出的最多。我只对OpenedDate的月份感兴趣,但我把它作为事后处理的日期。我试图在单个查询中检索我需要的所有数据。

我一直在尝试以下方面:

select
  dateadd (month, datediff(month, 0, a.OpenedDate), 0) as 'Date',
  c.AddressState as 'State',
  (
    select sum(x.Amount)
    from (
      select p.Amount
      from Payment p
      where p.AccountID = a.AccountID
    ) as x
  )
  from Account a
  inner join Customer c on c.CustomerID = a.CustomerID
  where ***
  group by
    dateadd(month, datediff(month, 0, a.OpenedDate), 0),
    c.AddressState

where子句包含Account表上的一些常规内容。该查询将不起作用,因为a.AccountID未包含在聚合函数中。

我是以正确的方式接近这个吗?如何检索我需要的数据,以便计算哪些州的客户支付最多?

3 个答案:

答案 0 :(得分:2)

如果您希望按月分组数据,则需要按月分组:

SELECT  AddressState, DATEPART(mm, OpenedDate), SUM(Amount)
FROM    Customer c
INNER JOIN Account a  ON a.CustomerID = c.CustomerID
INNER JOIN Payments p ON p.AccountID = a.AccountID
GROUP BY   AddressState, DATEPART(mm, OpenedDate)

显示月份数(1-12)和每个州的总金额。请注意,此示例不包括年份:无论年份如何,所有月份1的金额都会相加。如果你愿意,可以添加一个datepart(yy,OpenedDate)。

答案 1 :(得分:1)

  

换句话说,我试图找出每个国家每个月支付最多的费用

这个将为每个月选择最有利可图的州:

SELECT  *
FROM    (
        SELECT  yr, mon, AddressState, amt, ROW_NUMBER() OVER (PARTITION BY yr, mon, addressstate ORDER BY amt DESC) AS rn
        FROM    (
                SELECT  YEAR(OpenedDate) AS yr, MONTH(OpenedDate) AS mon, AddressState, SUM(Amount) AS amt
                FROM    Customer c
                JOIN    Account a
                ON      a.CustomerID = c.CustomerID
                JOIN    Payments p
                ON      p.AccountID = a.AccountID
                GROUP BY
                        YEAR(OpenedDate), MONTH(OpenedDate), AddressState
                )
        ) q
WHERE   rn = 1

将最后一个条件替换为ORDER BY yr, mon, amt DESC,以获取结果集中所有状态的列表:

SELECT  *
FROM    (
        SELECT  yr, mon, AddressState, amt, ROW_NUMBER() OVER (PARTITION BY yr, mon, addressstate ORDER BY amt DESC) AS rn
        FROM    (
                SELECT  YEAR(OpenedDate) AS yr, MONTH(OpenedDate) AS mon, AddressState, SUM(Amount) AS amt
                FROM    Customer c
                JOIN    Account a
                ON      a.CustomerID = c.CustomerID
                JOIN    Payments p
                ON      p.AccountID = a.AccountID
                GROUP BY
                        YEAR(OpenedDate), MONTH(OpenedDate), AddressState
                )
        ) q
ORDER BY
        yr, mon, amt DESC

答案 2 :(得分:0)

select
    AddressState,
    year(OpenedDate) as Yr,
    month(OpenedDate) as Mnth,
    sum(Payment) as SumPayment
from Customer c
    inner join Account a
        on c.CustomerID=a.CustomerID
    inner join Payment p
        on a.AccountID=p.AccountID
group by AddressState, month(OpenedDate)