3

トリッキーな SQL の質問があります。これは、SQL サーバー 2008 R2 に基づいています。

Log テーブルから、同じメッセージを持つ連続するレコードを結合しMSG( )、結合されたメッセージの数をカウントし ( COUNT)、重複したメッセージを削除する必要があります。これも日付範囲内で行う必要があるため、その範囲外のレコードはそのままにしておきます。

これをより理解しやすくするために、データの小さな例を次に示します。

ID  DATE       MSG  COUNT
1   2013-08-17 mail NULL
2   2013-08-17 mail NULL
3   2013-08-17 www  NULL
4   2013-08-18 www  NULL
5   2013-08-18 www  NULL
6   2013-08-18 www  NULL
7   2013-08-18 mail NULL
8   2013-08-18 www  NULL
9   2013-08-19 mail NULL
10  2013-08-19 mail NULL
11  2013-08-20 mail NULL
12  2013-08-20 mail NULL
13  2013-08-21 www  NULL
14  2013-08-22 mail NULL
15  2013-08-22 mail NULL
16  2013-08-23 mail NULL
17  2013-08-23 mail NULL
18  2013-08-23 mail NULL

結果は次のようになります。

ID  DATE       MSG  COUNT
1   2013-08-17 mail NULL
2   2013-08-17 mail NULL
3   2013-08-17 www  NULL
6   2013-08-18 www  3
7   2013-08-18 mail 1
8   2013-08-18 www  1
12  2013-08-20 mail 4
13  2013-08-21 www  1
15  2013-08-22 mail 2
16  2013-08-23 mail NULL
17  2013-08-23 mail NULL
18  2013-08-23 mail NULL

したがって、基本的に、クエリは

  1. 特定の日付範囲 (この例では から2013-08-18まで2013-08-22)内のデータのみを処理します。
  2. MSGフィールドのテキストに基づいて連続する行を結合する
  3. COUNT結合されたデータをカウントし、フィールドに値を設定します
  4. 重複レコードを削除します (この例では、ID 6 はそのままですが、ID 5 と ID 4 は削除する必要があります)。

私は SQL の専門家ではないので、助け、提案、または SQL クエリをいただければ幸いです。

4

3 に答える 3

1

私の考えは、2つのクエリでそれを行うことです:

(i)最初のものは、レコードを数えて更新するだけでした。

(ii) 2 つ目は、列にNULL値を持つ日付範囲を指定して、すべてのレコードを削除することでした。COUNT

編集:ステップ(i)を実行しましたが、削除するCOUNT値を保持できませんでした。NULLですべての行を更新しますCOUNTDELETEこれで、正しい行に移動するだけです。

ステップ(i) :

(MySQL の場合)

UPDATE tab ta JOIN 
    (SELECT date, msg, COUNT(*) AS cnt FROM tab GROUP BY date, msg) tb 
SET ta.count = tb.cnt 
WHERE ta.date = tb.date AND ta.msg = tb.msg AND 
ta.date BETWEEN 
    DATE('2013-08-18') AND DATE('2013-08-21');

PS:私が使用した構文DATEは MySQL 用です。MS SQL Server 用に適応させることができます。

(MS SQL Server の場合)

UPDATE ta 
SET ta.count = tb.cnt 
FROM tab ta, 
     (SELECT date, msg, COUNT(*) AS cnt FROM tab GROUP BY date, msg) tb 
WHERE ta.date = tb.date AND ta.msg = tb.msg AND ta.date 
BETWEEN CAST('2013-08-18' AS DATE) AND CAST('2013-08-20' AS DATE);
于 2013-09-17T13:07:04.290 に答える
1

これを試して:

DROP TABLE #temp 
GO
select
    * 
into #temp
from (
    select '1' as id,'2013-08-17' as [date], 'mail' as msg,'NULL' as [count] union all
    select '2','2013-08-17','mail','NULL' union all
    select '3','2013-08-17','www','NULL' union all
    select '4','2013-08-18','www','NULL' union all
    select '5','2013-08-18','www','NULL' union all
    select '6','2013-08-18','www','NULL' union all
    select '7','2013-08-18','mail','NULL' union all
    select '8','2013-08-18','www','NULL' union all
    select '9','2013-08-19','mail','NULL' union all
    select '10','2013-08-19','mail','NULL' union all
    select '11','2013-08-20','mail','NULL' union all
    select '12','2013-08-20','mail','NULL' union all
    select '13','2013-08-21','www','NULL' union all
    select '14','2013-08-22','mail','NULL' union all
    select '15','2013-08-22','mail','NULL' union all
    select '16','2013-08-23','mail','NULL' union all
    select '17','2013-08-23','mail','NULL' union all
    select '18','2013-08-23','mail','NULL'
) x
GO


select 
    t.*,
    rwn
from #temp t
join (
    select 
        id, [date], [msg], [rwn] = row_number() over(partition by [date], [msg] order by id )
    from #temp
    where 1=1
        and [date] between '2013-08-18' and '2013-08-22'
) x
    on t.id=x.id
 order by 
    t.date, t.msg

UPDATE用に変更してから、rwn> 1のすべての行を削除します

編集: データ型はおそらくテキストであるため、エラーの並べ替え/比較が行われます。テキストは本当に必要ですか?これはラージ オブジェクト データ型 (blob) であり、数 GB のテキストを格納できます。たとえば、これを varchar(8000) に変更してみてください。または、これらが本当に大きなメッセージである場合は、varchar(max) も同様です。

于 2013-09-17T13:11:50.683 に答える
1

こんにちは、これが役に立てば幸いです。私が理解している方法は、重複をグループ化して削除し、1つだけを保持する必要があるということです。私の英語でごめんなさい

DECLARE @Table_2 TABLE (ID INT, [DATE] date, MSG Varchar(50), [COUNT] int)
Declare @fromDate as date = '2013-08-18'
Declare @toDate as date = '2013-08-22'

INSERT INTO @Table_2 (ID, [DATE], MSG, [COUNT])
SELECT     MAX(DISTINCT ID) AS ID, DATE, MSG, COUNT(DATE) AS COUNT
FROM         dbo.Table_1
where [DATE] between @fromDate and @toDate
GROUP BY DATE, MSG



UPDATE Table_1 
SET [COUNT] = T2.COUNT 

FROM Table_1 AS T1 INNER JOIN
@Table_2 AS T2
ON T1.ID = T2.ID

WHERE T1.ID = T2.ID


DELETE T1
FROM Table_1 AS T1
FULL OUTER JOIN @Table_2 AS T2 
ON T1.DATE = T2.DATE AND T1.MSG = T2.MSG 

WHERE (T1.DATE = T2.DATE AND T1.MSG = T2.MSG) AND T1.ID != T2.ID 
于 2013-09-18T03:21:33.727 に答える