小编典典

我可以使用什么SQL从付款数据中检索计数?

sql

计数标准:每个月按学校服务类型对每个学校的学生人数(由唯一的学生ID索引)进行“真实”计数。

我当前正在使用MS-Access。我需要能够提取与以下示例数据类似的数据的数据库计数。每行都是付款观察。

样本数据:

Student ID |  School  | School Service Type | PaymentStartDate | PaymentEndDate |
   001          ABC              ED             01/02/2010         02/04/2012
   001          ABC              ED             01/02/2010         01/05/2010
   001          ABC              ED             04/02/2010         05/05/2010            
   001          DEF              EZ             01/02/2010         02/04/2012
   001                           RR             02/02/2012         02/03/2012
   002          ABC              ED             02/02/2010         02/03/2011
   002          ABC              EZ             02/02/2010         06/03/2010
   002          GHI              ED             02/04/2011         02/04/2012
   003          ABC              ED             02/02/2011         02/03/2012
   003          DEF              ED             01/02/2010         08/03/2010
   003                           RR             02/02/2011         02/03/2011
   004                           RR             02/02/2011         02/03/2011
   005          GHI              ED             08/02/2010         02/04/2011
   006          GHI              ED             08/02/2010         08/02/2010

我希望我的计数看起来像什么:

  Month  |  Year  | School | ED | EZ | RR |

   01       2010     ABC      1    0    0    
   01       2010     DEF      1    1    0
   01       2010     GHI      0    0    0
   02       2010     ABC      2    1    0
   03       2010     ABC      2    1    0

例子

愿望:我希望按服务类型,在整个学校中真实地统计学生人数, January 2010

最大的障碍-重复项

请看一下对的观察Student ID 001。在2010年1月至2012年2月期间,学校ABC收到了3笔款项,与Service Type (ED)001学生的款项完全相同。

我希望我在2010年1月ED在学校接受过服务的学生人数ABC返回1,因为当时只有一名学生(Student 001ED在那所学校接受过服务。

但是,当我使用交叉表按原样使用此数据检索我的计数时,它返回的值为2(对于两个学生)。原因是付款的#1和付款#2都Student 001符合我的2010年1月的月-年标准。

付款#1 符合条件,因为2010年1月位于付款日期范围01/02/2010-02/04/2012 *。

付款#2 也符合条件,因为2010年1月在付款日期范围01/02/2010-01/05/2010内。

#3付款 不符合标准,因为2010年1月不在该行的日期范围内(04/02/2010-05/05/2010)。

*您分别从PaymentStartDate和获得这些日期PaymentEndDate

我在这里准备了示例数据的Excel版本:链接到Excel文件

请记住:

  • PaymentStartDate和PaymentEndDate之间经过的时间在各个方面都非常不同,范围从0天到122天。

  • 很多时候,确实有独特的付款观察,其中PaymentStartDate和PaymentEndDate之间的时间为0天(请查看上面数据中学生ID 006的付款行)。因此,摆脱不符合指定的“ PaymentStartDate和PaymentEndDate之间的时间间隔”条件的行不是一种选择,因为很多时候它们不是我要摆脱的重复项。

  • 是的,对于某些服务类型,没有学校价值。

与往常一样,任何有关如何解决此重复问题以及如何在MS-Access中检索我的真实计数值的建议的有益建议都将受到赞赏。感谢您的时间。

编辑(2014年2月10日):更改了上面的计数输出,以反映我在帖子中提供的示例数据。我很抱歉以前没有这样做。


阅读 185

收藏
2021-04-14

共1个答案

小编典典

这是解决它的一种方法。对于名为[Payments]的表中的示例数据

Payment Row  Student ID  School  School Service Type  PaymentStartDate  PaymentEndDate
-----------  ----------  ------  -------------------  ----------------  --------------
          1  001         ABC     ED                   2010-01-02        2012-02-04    
          2  001         ABC     ED                   2010-01-02        2010-01-05    
          3  001         ABC     ED                   2010-04-02        2010-05-05    
          4  001         DEF     EZ                   2010-01-02        2012-02-04    
          5  001                 RR                   2012-02-02        2012-02-03    
          6  002         ABC     ED                   2010-02-02        2011-02-03    
          7  002         ABC     EZ                   2010-02-02        2010-06-03    
          8  002         GHI     ED                   2011-02-04        2012-02-04    
          9  003         ABC     ED                   2011-02-02        2012-02-03    
         10  003         DEF     ED                   2010-01-02        2010-08-03    
         11  003                 RR                   2011-02-02        2011-02-03    
         12  004                 RR                   2011-02-02        2011-02-03    
         13  005         GHI     ED                   2010-08-02        2011-02-04    
         14  006         GHI     ED                   2010-08-02        2010-08-02

如果我们在Access中创建名为[PaymentsYearMonth]的保存的查询

SELECT 
    [Student ID], 
    School, 
    [School Service Type], 
    (Year(PaymentStartDate) * 100) + Month(PaymentStartDate) AS StartYYYYMM, 
    (Year(PaymentEndDate) * 100) + Month(PaymentEndDate) AS EndYYYYMM
FROM Payments

它会给我们

Student ID  School  School Service Type  StartYYYYMM  EndYYYYMM
----------  ------  -------------------  -----------  ---------
001         ABC     ED                        201001     201202
001         ABC     ED                        201001     201001
001         ABC     ED                        201004     201005
001         DEF     EZ                        201001     201202
001                 RR                        201202     201202
002         ABC     ED                        201002     201102
002         ABC     EZ                        201002     201006
002         GHI     ED                        201102     201202
003         ABC     ED                        201102     201202
003         DEF     ED                        201001     201008
003                 RR                        201102     201102
004                 RR                        201102     201102
005         GHI     ED                        201008     201102
006         GHI     ED                        201008     201008

要生成数据覆盖的年/月对,我们可以使用名为[MonthNumbers]的表

MonthNumber
-----------
          1
          2
          3
          4
          5
          6
          7
          8
          9
         10
         11
         12

以及一个名为[YearNumbers]的表格,该表格涵盖了数据中可能出现的每年。为了安全起见,每年可能包括从1901年到2525年的时间,但为了说明起见,我们仅使用

YearNumber
----------
      2009
      2010
      2011
      2012
      2013

现在,我们可以创建一个名为[MonthsToReport]的保存的查询,为我们提供可能产生结果的行

SELECT
    yn.YearNumber,
    mn.MonthNumber,
    (yn.YearNumber * 100) + mn.MonthNumber AS YYYYMM
FROM
    YearNumbers AS yn,
    MonthNumbers AS mn
WHERE ((yn.YearNumber * 100) + mn.MonthNumber)>=DMin("StartYYYYMM","PaymentsYearMonth")
    AND ((yn.YearNumber * 100) + mn.MonthNumber)<=DMax("EndYYYYMM","PaymentsYearMonth")

按年份和月份排序看起来像

YearNumber  MonthNumber  YYYYMM
----------  -----------  ------
      2010            1  201001
      2010            2  201002
      2010            3  201003
      2010            4  201004
      2010            5  201005
      2010            6  201006
      2010            7  201007
      2010            8  201008
      2010            9  201009
      2010           10  201010
      2010           11  201011
      2010           12  201012
      2011            1  201101
      2011            2  201102
      2011            3  201103
      2011            4  201104
      2011            5  201105
      2011            6  201106
      2011            7  201107
      2011            8  201108
      2011            9  201109
      2011           10  201110
      2011           11  201111
      2011           12  201112
      2012            1  201201
      2012            2  201202

现在创建一个查询,为我们提供年/月/学生/学校/类型的不同实例

SELECT DISTINCT
    mtr.YearNumber,
    mtr.MonthNumber,
    pym.[Student ID],
    pym.School,
    pym.[School Service Type]
FROM
    MonthsToReport AS mtr
    INNER JOIN
    PaymentsYearMonth AS pym
        ON mtr.YYYYMM>=pym.StartYYYYMM 
            AND mtr.YYYYMM<=pym.EndYYYYMM

…在汇总查询中将其包装起来以计算(现在是唯一的)[Student ID]值

SELECT
    YearNumber,
    MonthNumber,
    School,
    [School Service Type],
    COUNT(*) AS CountOfStudents
FROM
    (
        SELECT DISTINCT
            mtr.YearNumber,
            mtr.MonthNumber,
            pym.[Student ID],
            pym.School,
            pym.[School Service Type]
        FROM
            MonthsToReport AS mtr
            INNER JOIN
            PaymentsYearMonth AS pym
                ON mtr.YYYYMM>=pym.StartYYYYMM 
                    AND mtr.YYYYMM<=pym.EndYYYYMM
    ) AS distinctQuery
GROUP BY 
    YearNumber,
    MonthNumber,
    School,
    [School Service Type]

然后将 用作我们的交叉表查询中的FROM子查询

TRANSFORM Nz(First(CountOfStudents),0) AS n
SELECT 
    YearNumber,
    MonthNumber,
    School
FROM
    (
        SELECT
            YearNumber,
            MonthNumber,
            School,
            [School Service Type],
            COUNT(*) AS CountOfStudents
        FROM
            (
                SELECT DISTINCT
                    mtr.YearNumber,
                    mtr.MonthNumber,
                    pym.[Student ID],
                    pym.School,
                    pym.[School Service Type]
                FROM
                    MonthsToReport AS mtr
                    INNER JOIN
                    PaymentsYearMonth AS pym
                        ON mtr.YYYYMM>=pym.StartYYYYMM 
                            AND mtr.YYYYMM<=pym.EndYYYYMM
            ) AS distinctQuery
        GROUP BY 
            YearNumber,
            MonthNumber,
            School,
            [School Service Type]
    ) AS countQuery
GROUP BY
    YearNumber,
    MonthNumber,
    School
PIVOT [School Service Type]

返回

YearNumber  MonthNumber  School  ED  EZ  RR
----------  -----------  ------  --  --  --
      2010            1  ABC     1   0   0 
      2010            1  DEF     1   1   0 
      2010            2  ABC     2   1   0 
      2010            2  DEF     1   1   0 
      2010            3  ABC     2   1   0 
      2010            3  DEF     1   1   0 
      2010            4  ABC     2   1   0 
      2010            4  DEF     1   1   0 
      2010            5  ABC     2   1   0 
      2010            5  DEF     1   1   0 
      2010            6  ABC     2   1   0 
      2010            6  DEF     1   1   0 
      2010            7  ABC     2   0   0 
      2010            7  DEF     1   1   0 
      2010            8  ABC     2   0   0 
      2010            8  DEF     1   1   0 
      2010            8  GHI     2   0   0 
      2010            9  ABC     2   0   0 
      2010            9  DEF     0   1   0 
      2010            9  GHI     1   0   0 
      2010           10  ABC     2   0   0 
      2010           10  DEF     0   1   0 
      2010           10  GHI     1   0   0 
      2010           11  ABC     2   0   0 
      2010           11  DEF     0   1   0 
      2010           11  GHI     1   0   0 
      2010           12  ABC     2   0   0 
      2010           12  DEF     0   1   0 
      2010           12  GHI     1   0   0 
      2011            1  ABC     2   0   0 
      2011            1  DEF     0   1   0 
      2011            1  GHI     1   0   0 
      2011            2          0   0   2 
      2011            2  ABC     3   0   0 
      2011            2  DEF     0   1   0 
      2011            2  GHI     2   0   0 
      2011            3  ABC     2   0   0 
      2011            3  DEF     0   1   0 
      2011            3  GHI     1   0   0 
      2011            4  ABC     2   0   0 
      2011            4  DEF     0   1   0 
      2011            4  GHI     1   0   0 
      2011            5  ABC     2   0   0 
      2011            5  DEF     0   1   0 
      2011            5  GHI     1   0   0 
      2011            6  ABC     2   0   0 
      2011            6  DEF     0   1   0 
      2011            6  GHI     1   0   0 
      2011            7  ABC     2   0   0 
      2011            7  DEF     0   1   0 
      2011            7  GHI     1   0   0 
      2011            8  ABC     2   0   0 
      2011            8  DEF     0   1   0 
      2011            8  GHI     1   0   0 
      2011            9  ABC     2   0   0 
      2011            9  DEF     0   1   0 
      2011            9  GHI     1   0   0 
      2011           10  ABC     2   0   0 
      2011           10  DEF     0   1   0 
      2011           10  GHI     1   0   0 
      2011           11  ABC     2   0   0 
      2011           11  DEF     0   1   0 
      2011           11  GHI     1   0   0 
      2011           12  ABC     2   0   0 
      2011           12  DEF     0   1   0 
      2011           12  GHI     1   0   0 
      2012            1  ABC     2   0   0 
      2012            1  DEF     0   1   0 
      2012            1  GHI     1   0   0 
      2012            2          0   0   1 
      2012            2  ABC     2   0   0 
      2012            2  DEF     0   1   0 
      2012            2  GHI     1   0   0
2021-04-14