2

次のようなデータセットがあります。

TrxDate     DayOfWk TrxHour TrxName Succeeded
Oct 21 2012 Sunday  0       signon  1
Oct 21 2012 Sunday  0       Bal     1
Oct 21 2012 Sunday  0       Bal     1
Oct 21 2012 Sunday  0       hist    1
Oct 21 2012 Sunday  0       Bal     1

実際には、INNER JOINこのような結果セットを取得するには、uniqueID を取得するために an を使用する必要がありますが、それは細かいことです。私が与えられた要件は次のとおりです。

  • 日付、曜日、時間に基づいてグループ化します。
  • グループごとのサインオン成功数を出力します。
  • グループごとのサインオン失敗回数を出力します。
  • 各グループのサインオンの総数 (成功 + 失敗) を出力します。
  • 各グループの合計トランザクション数を出力します (基本的にはCount(UniqueId))。

したがって、出力は次のようになります。

Date        Day of Week Hour    Login Success   Login Failures  Total Logins    Total Transactions
11/15/2012  5           22      12,000          1,000           13,000          25,000 
11/15/2012  5           23      15,223          1,500           16,723          33,000 
11/16/2012  6           0       22,000          3,000           25,000          12,554 
11/16/2012  6           1       18,000          2,000           20,000          15,899 

Date明らかに、とがどのように表示されるかについてのわずかな文体上の違いがありDayOfWkます。それらは重要ではありません。

問題:INNER JOINからすべてを一時テーブルにダンプし、拡張クエリを実行して、結果セットが必要とするさまざまな方法でその一時テーブルをカタログ化する以外に、これを行うためのより良い方法はありません。数十万行の 2 つのINNER JOINテーブルに接続します。この手法は遅く、速度が高く、肥大化してメモリが消費されます。この解決策は機能しますが、それよりも自分の仕事にもう少し誇りを持ちたいと思います! これをもう少し優雅に達成するためのアイデアはありますか?

私は以下の答えに大きな亀裂を入れました。私のクエリは次のようになります。

SELECT
LEFT(first.EntryDateTime, 11) AS [Date]
,DATENAME(weekday, first.EntryDateTime) AS [Day of Week]
,DATEPART(hh, first.EntryDateTime) AS [Hour]
,SUM(CASE WHEN second.TrxName = 'signon' AND first.Succeeded = 1 THEN 1 ELSE 0 END) AS [Login Success]
,SUM(CASE WHEN second.TrxName = 'signon' AND first.Succeeded = 1 THEN 0 ELSE 1 END) AS [Login Failure]
,SUM(CASE WHEN second.TrxName = 'signon' THEN 1 ELSE 0 END) AS [Total Logins]
,COUNT(first.UniqueId) AS [Total Transactions]

FROM
dbo.TheFirstPlace first (NOLOCK)
INNER JOIN
dbo.TheSecondPlace second (NOLOCK)
ON  first.TrxUniqueId = second.TrxUniqueId
WHERE first.EntryDateTime > DATEADD(day, -7, cast(GETDATE() As Date))
GROUP BY
    LEFT(first.EntryDateTime, 11),
    DATENAME(weekday, first.EntryDateTime),
    DATEPART(hh, first.EntryDateTime)

そして、私の結果セットは次のようになります。

Date        Day of Week Hour    Login Success   Login Failure   Total Logins    Total Transactions
Nov  9 2012 Friday      0       554             26245           595             26799
Nov  9 2012 Friday      1       2113            120569          2509            122682
Nov  9 2012 Friday      2       1675            102058          1743            103733

明らかに、ここでの計算はまったく機能せず、その理由について私は混乱しています。

4

1 に答える 1

4

CASEステートメントとステートメントを組み合わせて使用​​した場合、おそらくデータで 1 回のパスを作成できますSUMCOUNTこれは、複数のクエリを実行するよりも効率的である可能性があります...次のようなものです:

SELECT
    [Date],
    [Day of Week],
    [Hour],
    SUM(CASE WHEN TrxName = 'signon' AND Succeeded = 1 THEN 1 ELSE 0 END) AS [Login Success],
    SUM(CASE WHEN TrxName = 'signon' AND Succeeded = 0 THEN 1 ELSE 0 END) AS [Login Failure],
    SUM(CASE WHEN TrxName = 'signon' 1 ELSE 0 END) AS [Total Logins],
    COUNT(UniqueId) AS [Total Transactions]
FROM
    YourTable
GROUP BY
    [Date],
    [Day of Week],
    [Hour]
于 2012-11-16T20:40:47.543 に答える