从具有多笔付款的客户的表格中仅选择一笔付款

时间:2017-01-06 17:30:15

标签: sql sql-server

我有一张名为"付款"在那里我存储了我的客户的所有付款,我需要做一个选择来计算给定月份的非付款率。

客户可以在该月支付多次付款,但我应该只计算一次:1如果付款已完成,如果付款已付款则为0。 例如:

+----+------------+--------+
| ID |  DATEDUE   | AMOUNT |
+----+------------+--------+
|  1 | 2016-11-01 | 0      |
|  1 | 2016-11-15 | 20.00  |
|  2 | 2016-11-10 | 0      |
+----+------------+--------+

我期望的结果来自11月的比率:

+----+------------+--------+
| ID |  DATEDUE   | AMOUNT |
+----+------------+--------+
|  1 | 2016-11-15 | 20.00  |
|  2 | 2016-11-10 | 0      |
+----+------------+--------+

所以费率将是50%。

但如果选择是:

SELECT * FROM payment WHERE DATEDUE BETWEEN '2016-11-01' AND '2016-11-30'

它将返回我3行,速率将是66%,女巫是错误的。想法?

PS:这是真实表的一个更简单的例子。真正的查询有很多列,子选择等。

3 个答案:

答案 0 :(得分:1)

试试这个

SELECT
    id
    , SUM(AMOUNT) AS AMOUNT
FROM
    Payment
GROUP BY
    id;

如果您想要其他列,这可能会有所帮助。

WITH cte (
    SELECT
        id
        , ROW_NUMBER() OVER (PARTITION BY ID ORDER BY AMOUNT DESC ) AS RowNum
        -- other row
)
SELECT *
FROM
    cte
WHERE
    RowNum = 1;

答案 1 :(得分:1)

听起来您需要按照客户对结果进行分区。

SELECT        TOP 1 WITH TIES

              ID,
              DATEDUE,
              AMOUNT

ORDER BY      ROW_NUMBER() OVER (PARTITION BY ID ORDER BY AMOUNT DESC)

WHERE DATEDUE BETWEEN '2016-11-01' AND '2016-11-30'

PS:有些人不赞成BETWEEN运营商。为清楚起见,最好避免它:

答案 2 :(得分:0)

要计算费率,您可以使用显式除法:

select 1 - count(distinct case when amount > 0 then id end) / count(*)
from payment
where . . .;

或者,或许更容易理解:

select avg(flag * 1.0)
from (select id, (case when max(amount) > 0 then 0 else 1 end) as flag
      from payment
      where . . .
      group by id
     ) i