1

意识到我之前提出的另一个问题可能太难了,我正在改变我的要求。

我在一家信用卡公司工作。我们的数据库有一个客户表和一个交易表。客户表中的字段是 SSN 和 CustomerKey。交易表中的字段是 CustomerKey、交易日期 (Transdate) 和交易金额 (TransAmt)。

我需要一个查询,可以识别每个 ssn,其中任何交易金额的总和在 2012 年的两天内 > 1000。如果 ssn 在两天内的交易金额 > 1000,我需要查询返回所有该 ssn 的交易。

以下是交易表中原始数据的示例:

Trans#-----CustKey-----Date--------金额
1-----------12345----01/01/12--------$600
2-----------12345----01/02/12--------$500
3-----------67890----01/03/12--------$10
4-----------98765----04/01/12--------$600
5-----------43210----04/02/12--------$600
6-----------43210----04/03/12--------$100
7-----------13579----04/02/12--------$600
8-----------24568----04/03/12--------$100

以下是客户表中原始数据的示例:

客户密钥-----SSN
12345------123456789
67890------123456789
98765------987654321
43210------987654321
13579------246801357
24568------246801357

这是我需要的结果:

Trans#------SSN---------日期---------金额
1--------123456789----01/01/12---------$600
2--------123456789----01/02/12---------$500
3--------123456789----01/03/12----------$10
4--------987654321----04/01/12---------$600
5--------987654321----04/02/12---------$600
6--------987654321----04/03/12---------$100

正如您在我的结果中看到的,包括SSN 123456789 和 987654321 的所有交易,但排除了 SSN 246801357。

4

3 回答 3

1

一种方法是在一年内每两天滚动一次。这是一个SQL Fiddle示例。这个想法很简单:

1)创建一个临时表来存储所有匹配的客户

create table CustomersToShow
(
    SSN int
)

2) 循环一年并用符合金额标准的客户填充临时表

declare @firstDayOfTheYear datetime = '1/1/2012';
declare @lastDayOfTheYear datetime = '12/31/2012';
declare @currentDate datetime = @firstDayOfTheYear;
declare @amountThreshold money = 1000;

while @currentDate <= @lastDayOfTheYear
begin
    insert into CustomersToShow(SSN)
    select b.SSN
    from transactions a
        join customers b
        on a.CustKey = b.CustKey
    where TransactionDate >= @currentDate
        and TransactionDate <= DATEADD(day, 2, @currentDate)
    group by b.SSN  
    having SUM(a.TransactionAmount) >= @amountThreshold

    set @currentDate = DATEADD(day,2,@currentDate)
end

3)然后只需选择

select a.TransNumber, b.SSN, a.TransactionDate, a.TransactionAmount 
from transactions a
    join customers b
    on a.CustKey = b.CustKey
    join CustomersToShow c
    on b.SSN = c.SSN

注意:这会很慢...

于 2012-09-20T01:13:52.410 回答
0

如果你没看错的话,这很容易并且非常适合基于集合的逻辑。您只需加入一个包含您感兴趣的每个日期范围的表。每个 T-SQL 数据库(Oracle 内置)都应该有一个名为的实用程序表integers- 它经常非常有用:

CREATE TABLE integers ( n smallint, constraint PK_integers primary key clustered (n))
INSERT integers select top 1000 row_number() over (order by o.id) from sysobjects o cross join sysobjects

您的日期表如下所示:

SELECT dateadd(day, n-1, '2012') AS dtFrom, dateadd(day, n+1, '2012') AS dtTo
from integers where n <= 366

然后,您可以(缩写):

SELECT ssn, dtFrom
FROM yourTables t
    JOIN ( SELECT dateadd(day, n-1, '2012') as dtFrom, dateadd(day, n+1, '2012') AS dtTo
           from integers where n <= 366 ) d on t.date between d.dtFrom and d.dtTo
GROUP BY ssn, dtFrom
HAVING sum(amount) > 1000

您可以选择所有交易:

WHERE ssn in ( SELECT distinct ssn from ( <above query> ) t )
于 2013-02-15T14:23:35.580 回答
0

虽然您可能会想出一种通过标准 SQL 完成此操作的 hacky 方法,但这是 IMO 更适合通过代码解决的问题(即,不是通过基于集合的逻辑/SQL)。

如果按 customerKey 和 date 对交易列表进行排序,然后循环遍历数据,则很容易解决。理想情况下,我会在代码中执行此操作,但也可以编写存储过程并使用循环和游标。

于 2012-09-19T21:50:42.370 回答