1

以前に尋ねた別の質問は難しすぎるかもしれないことに気づき、要件を変更しています。

私はクレジットカード会社で働いています。私たちのデータベースには、顧客テーブルとトランザクションテーブルがあります。customerテーブルのフィールドは、SSNとCustomerKeyです。トランザクションテーブルのフィールドは、CustomerKey、トランザクション日付(Transdate)、およびトランザクション金額(TransAmt)です。

2012年の2日間でトランザクション金額が1000を超える各ssnを識別できるクエリが必要です。ssnのトランザクション量が2日間で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

Customerテーブルの生データの例を次に示します。

CustKey ----- 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のすべてのトランザクションが含まれ、SSN246801357は除外されました。

4

3 に答える 3

1

これを行う 1 つの方法は、1 年のうちに 2 日間の期間ごとにロールオーバーすることです。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 を介してこれを行うためのハックな方法を考え出すことができますが、これは IMO がコード (つまり、セットベースのロジック/SQL ではなく) で解決するのに適しているという問題です。

トランザクション リストを customerKey と日付で並べ替えてから、データをループすると簡単に解決できます。コードでこれを行うのが理想的ですが、別の方法として、ストアド プロシージャを記述し、ループとカーソルを使用することもできます。

于 2012-09-19T21:50:42.370 に答える