SQLite中的聚合

SQLite中的聚合,sql,database,sqlite,aggregate-functions,data-analysis,Sql,Database,Sqlite,Aggregate Functions,Data Analysis,我希望构造一个SQL查询,它能够按月汇总分期付款值。通常这不会太难,因为您只需将分期付款值和按月份分组即可。然而,问题并不是那么容易,在文章的其余部分,我将说明为什么,并寻求人们能够提供的任何帮助 首先,重要的是要注意分期付款列。其中,分期付款为1,意味着总价值在购买时支付。如果分期付款大于1,这意味着总价值在当月以及后续月份支付。例如,如果我们看到transaction\u id9和10,这是一笔100美元的交易,分两期付款,这意味着50美元将在2月份支付,50美元将在3月份支付 考虑到我们想

我希望构造一个SQL查询,它能够按月汇总分期付款值。通常这不会太难,因为您只需将分期付款值和
按月份分组即可。然而,问题并不是那么容易,在文章的其余部分,我将说明为什么,并寻求人们能够提供的任何帮助

首先,重要的是要注意
分期付款
列。其中,
分期付款
为1,意味着总价值在购买时支付。如果
分期付款
大于1,这意味着总价值在当月以及后续月份支付。例如,如果我们看到
transaction\u id
9和10,这是一笔100美元的交易,分两期付款,这意味着50美元将在2月份支付,50美元将在3月份支付

考虑到我们想要查看
信用卡的每月账单\u id=11111111
。如果我们查看
分期付款
列,我们可以看到正确的输出应如下所示:

  • 一月:19.99+75.3
  • 二月:1337+75.3
  • 三月:75.3
再说一次,需要明确的是,3月份的75.3是因为我们在1月份有一笔3分期付款的交易,这意味着客户将在1月、2月和3月收取75.3的费用。问题是我不知道如何根据给定的数据创建三月的类别

首先,我在SQL中重新创建了表,并且可以通过下面的SQLite查询轻松地按月获取卡的所有事务

select strftime('%m', transaction_date) as Month, total_value, installment_value, installments 
from transactions 
WHERE credit_card_id = '11111111';
它输出一个如下所示的表

但是,如何将3个分期付款期拆分为01、02和03并不明显,因此我创建了一个新表,其中包含一列
txn
,这意味着为可以视为1组的唯一交易提供一个id

CREATE TABLE transactions (
    transaction_id int primary key,
    credit_card_id int,
    transaction_date timestamp,
    merchant_name varchar(256),
    total_value decimal(19,4),
    installment_value decimal(19,4),
    installments int,
    txn int
);

insert into transactions values(1,11111111,'2018-01-10T00:00:00','Colorful Soaps', 19.99, 19.99, 1, 1);
insert into transactions values(2,22222222,'2018-01-11T00:01:00','Cantina da Mamma',43.5,43.5,1,2);
insert into transactions values(3,33333333,'2018-01-12T01:02:00','Boulevard Hotel',129,129,1,3);
insert into transactions values(4,11111111,'2018-01-15T11:11:11','Micas Bar',225.9,75.3,3,4);
insert into transactions values(5,11111111,'2018-01-15T11:11:11','Micas Bar',225.9,75.3,3,4);
insert into transactions values(6,11111111,'2018-01-15T11:11:11','Micas Bar',225.9,75.3,3,4);
insert into transactions values(7,22222222,'2018-01-18T22:10:01','IPear Store',9999.99,9999.99,1,5);
insert into transactions values(8,11111111,'2018-02-20T21:08:32','Forrest Paintball',1337,1337,1,6);
insert into transactions values(9,44444444,'2018-02-22T00:05:30','Unicorn Costumes',100,50,2,7);
insert into transactions values(10,44444444,'2018-02-22T00:05:30','Unicorn Costumes',100,50,2,7);
我的问题是

  • 是否有可能在SQLite中获得我上面识别的格式的输出?如果有,如何获得
  • 我是否必须有
    txn
    列才能获得此信息

  • 谢谢您的帮助。

    SQLlite有
    行号()
    (选中此处)


    分期付款超过两年时就会出现问题。你得做那部分。我会在函数中写这个代码(当……时),它会使整个查询更加清晰。

    < P>假设你运行SQLite 3.25 +版本,考虑使用它创建一个相同的CuffiTyCARIDID和TraceActualDead运行的计数,并使用这个值将需要的月份添加到事务日期。从那里开始,根据新的计算日期、安装日期进行聚合


    使用PostgreSQL,因为AFAIK没有在线FIDLE(SQLFIDLE、SQLiteonline、DBFIDLE等)支持带有窗口函数的SQLite

    这里有一个解决方案,它不需要行编号/将在更旧的SQLite(基本上支持日期()的任何版本)中工作。。 它只是依赖于一个日历表的连接(可以使用多种技术生成该表,但在链接的示例中,我只是通过创建一个表并直接插入查询所需的数据来生成N行),该日历表在每个月的第一天有一行。它使用笛卡尔连接条件,例如,每支付3次分期付款,就会产生3行:

    select 
      t.credit_card_id,
      date(cal.d, '-1 month') as month_of_installment,
      sum(t.installment_value)
    from
      cal inner join transactions t on
      t.transaction_date between date(cal.d, '-'||installments||' months') and cal.d
    group by
      t.credit_card_id,
      date(cal.d, '-1 month')
    
    您可以在以下位置查看设置:

    顺便说一句,您的问题或示例数据中出现了一些问题

    信用卡ID 11111111的每月付款为:

    2018-01   245.89
    2018-02   1562.9
    2018-03   225.9
    
    您的示例数据有3笔同时向Micas Bar付款。我们知道它们是不同的,因为它们有不同的事务ID,尽管其他数据相同。因此,一月份是75.3+75.3+75.3+19.99,而不仅仅是问题所说的19.99+75.3

    要查看查询工作方式的更多信息,请运行非分组表单:

    select 
      t.credit_card_id,
      date(cal.d, '-1 month') as month_of_installment,
      t.*
    from
      cal inner join transactions t on
      t.transaction_date between date(cal.d, '-'||installments||' months') and cal.d
    order by
      t.credit_card_id,
      date(cal.d, '-1 month')
    

    我遇到的大多数DBA都主张在db中使用一个数字/日期表来生成这样的查询—这是一种快速生成行序列的方法,在一个月内没有事务的情况下,它为您提供了一个可以加入的行(您可以将事务表左键连接到日历表,在没有事务的月份中获得一行,总计为0)。为未来100年生成一组月/日行是一个简单的一次性操作,请小心,当分期付款+事务日超过一年时,它将失败。我试图在回答中警告这一点(如有需要).SNR,你能解释为什么/如何在分期付款超过两年时失败吗?修改表中12月分期付款大于1的数据。接受的答案将失败。如果分期付款日期大于12月13日,我的答案将失败。只要你的日历足够大,@Caius Jard answer it不会失败。答案必须是,因为现在每个信用卡id生成的行太多,我们无法获得预期结果。@g.humpkins(编辑已发送)您可以通过使用
    内部联接的输出,在
    from
    子句中使用
    select distinct
    来实现要求。您将获得预期的结果。但是可能有更好的方法来实现这一点,让我们拭目以待……当分期大于1时,必须为每个月传播分期值。编辑答案以达到要求。
    2018-01   245.89
    2018-02   1562.9
    2018-03   225.9
    
    select 
      t.credit_card_id,
      date(cal.d, '-1 month') as month_of_installment,
      t.*
    from
      cal inner join transactions t on
      t.transaction_date between date(cal.d, '-'||installments||' months') and cal.d
    order by
      t.credit_card_id,
      date(cal.d, '-1 month')