SQL [Oracle]:计算具有相同客户端ID的先前记录的数量

时间:2016-06-02 11:47:57

标签: sql oracle

在网上进行了简短的搜索,看看是否已经存在答案。无法找到解决这种特殊情况的任何事情(这是一个惊喜,因为我认为这是相当普遍的。)

基本上我有一个表记录了服务的注册,以及客户注册的ID,以及注册的开始和结束日期。请参阅下面的表结构示例:

Reg ID | Client ID | Reg Start  | Reg End

R6       C1          01-06-2016   Null
R5       C2          20-05-2016   02-06-2016
R4       C2          14-03-2016   11-05-2016
R3       C1          10-03-2016   05-05-2016
R2       C2          28-01-2016   02-02-2016
R1       C2          10-11-2015   23-12-2015   

我想要做的是从表中提取记录,但也添加一个列,该列返回表中每个记录具有相同客户端ID的先前注册的数量。为了清楚起见,我只想计算具有相同客户ID并且开始日期小于记录的每条记录的注册。

因此,成功的查询将返回以下输出:

Reg ID | Client ID | Reg Start  | Reg End    | # previous reg

R6       C1          01-06-2016   Null         1
R5       C2          20-05-2016   02-06-2016   3
R4       C2          14-03-2016   11-05-2016   2
R3       C1          10-03-2016   05-05-2016   0
R2       C2          28-01-2016   02-02-2016   1
R1       C2          10-11-2015   23-12-2015   0

有没有人有过这样做的经验,可以提供可行的解决方案?

我最初的思考过程是创建一个子查询来计算按客户端ID分组的注册,然后使用客户端ID将其连接到我的主查询。例如:

SELECT
t1.reg_id
t1.client_id
t1.reg_start
t1.reg_end
FROM registrations t1
JOIN
  (SELECT
   client_id
   count(reg_id)
   FROM registrations
   GROUP BY client_id) t2
ON t1.client_id = t2.client_id

但是,这将返回每个记录的给定客户端注册的计数,其中我特别要求之前的注册。

蜂巢头脑可以提供的任何输入都将非常感激。我认为我在目前的SQL知识非常有限的情况下打了一针墙:/

另外我应该提一下,我正在使用Oracle数据库!

4 个答案:

答案 0 :(得分:2)

您可以使用row_number()

执行此操作
select r.*,
       (row_number() over (partition by client_id order by reg_start) - 1) as cnt
from registrations r;

答案 1 :(得分:2)

这可以通过窗口函数和运行总和来完成:

select reg_id, client_id, reg_start, reg_end,
       count(*) over (partition by client_id order by reg_start) - 1 as previous_reg
from registrations
order by reg_start desc;

答案 2 :(得分:1)

在SQL Server中,您可以使用以下查询:

SELECT [Reg ID], [Client ID], Reg_Start, Reg_End,
       COUNT(*) OVER (PARTITION BY [Client ID] ORDER BY Reg_Start) - 1
FROM mytable

COUNT,当应用ORDER BY子句时,返回记录计数的运行总计。如果这在Oracle中可用,那么它应该返回您想要的值。

答案 3 :(得分:0)

在我看来,最简单的方法是在主查询的SELECT语句中构建子查询,如下所示:

SELECT 
    t1.*, 
    (
        SELECT COUNT(*) 
        FROM registrations t2 
        WHERE t2.client_id = t1.client_id
          AND t2.reg_start < t1.reg_start
    ) AS previous_reg
FROM registrations t1
ORDER BY reg_id DESC