列出符合条件的交易

时间:2012-09-19 21:40:50

标签: sql

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

我在一家信用卡公司工作。我们的数据库有一个客户表和一个事务表。 customer表中的字段是SSN和CustomerKey。事务表中的字段是CustomerKey,事务日期(Transdate)和事务数量(TransAmt)。

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

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

Trans#-----CustKey-----Date--------Amount
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

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

CustKey-----SSN
12345------123456789
67890------123456789
98765------987654321
43210------987654321
13579------246801357
24568------246801357

以下是我需要的结果:

Trans#------SSN---------Date---------Amount
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。

3 个答案:

答案 0 :(得分: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

注意:这会很慢......

答案 1 :(得分:0)

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

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

答案 2 :(得分: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 )