1

私はこのテーブルを持っています:

table session(
ID number,
SessionID VarChar,
Date,
Filter
)

このテーブルには、次のような検索情報が含まれています。

ID  SessionID                   Date                filter
4   peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    meagPixel=5
6   peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    brand=Canon
7   peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    brand=Canon&meagPixel=12.1
8   peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    brand=Canon
10  peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    brand=Nikon
12  peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    meagPixel=12.1
13  peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    meagPixel=12.1&opticalZoom=True
14  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    meagPixel=12.1&opticalZoom=True&brand=Panasonic
16  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    price=500.00
18  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    price=499.00
19  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    price=499.00&brand=Olympus
21  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    zoomRange=2000
22  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    zoomRange=2000&brand=Leica
23  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    zoomRange=2000&brand=Leica&price=1995.00
24  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True
25  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2
26  peqq421gaspts3nuulq5mwcq    24/05/2012 13:50    zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2&weight=345
27  peqq421gaspts3nuulq5mwcq    24/05/2012 13:58    zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2
41  poiq41111spts00000q5aaaa    27/05/2012 13:48    meagPixel=5

ユニークな検索を取得したい。固有の検索は次のとおりです。

  • ユーザー(セッション)の最長検索(フィルター)
  • 最初のフィルターに変更がある場合 - 新しい検索 (フィルター) として処理する必要がありました

ASP.NET は SessionID が一意であることを保証しないため (SessionID,Date) は一意です。

私は遠くに行きませんでした:

SELECT        MAX(Filter)
FROM            Session
GROUP BY SessionID

ところで、私が与えたテーブル データの例の結果は次のようになります。

ID  SessionID                   Date                filter              
4   peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    meagPixel=5     
7   peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    brand=Canon&meagPixel=12.1      
10  peqq421gaspts3nuulq5mwcq    24/05/2012 13:48    brand=Nikon     
14  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    meagPixel=12.1&opticalZoom=True&brand=Panasonic     
16  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    price=500.00        
19  peqq421gaspts3nuulq5mwcq    24/05/2012 13:49    price=499.00&brand=Olympus      
26  peqq421gaspts3nuulq5mwcq    24/05/2012 13:50    zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2&weight=345     
41  poiq41111spts00000q5aaaa    27/05/2012 13:48    meagPixel=5     

助けてくれてありがとう。

4

3 に答える 3

1

@GarethD - スキーマと挿入クエリの Tx。私は少し異なるアプローチを試みました。これがすべてのシナリオで機能するかどうかはわかりません。mysql と mssql で動作しました。

          select * 
          from tsession t1 
          where  not exists (
                             select * 
                             from tsession t2 
                             where t2.filter  like concat(t1.filter,'%') 
                             and t1.filter<>t2.filter 
                             and t1.sessionid=t2.sessionid) 
          order by id;

これにより、質問で必要な正確な結果が得られます。

于 2012-06-07T05:06:20.123 に答える
0

まず、サンプル データにエラーがあるようです。行 25、26、および 27 はすべて最終データに表示されるはずです。27 は、そのセッション ID と日付の組み合わせの唯一のエントリであるため、当然のことです。

上記が正しいと仮定すると、私はあなたのロジックを正しく確立したと思います。

ステップ 1 では、各フィルタの最初の検索用語と、セッション内で発生した順序を定義します。

;WITH CTE AS
(   SELECT  *, 
            SUBSTRING(Filter, 1, CASE WHEN CHARINDEX('&', Filter) = 0 THEN LEN(Filter) ELSE CHARINDEX('&', Filter) - 1 END) [FirstTerm],
    FROM    Session
)

次のステップは、各検索が新しい検索なのか、前の検索の継続なのかを判断することです。これは、セッション内の以前の検索用語を取得し (最後の CTE で SessionOrder が定義された理由)、最初の検索用語が同じかどうかを確認することによって行われます。

, CTE2 AS
(   SELECT  T1.*, 
            CASE WHEN T1.SessionOrder = 1 OR T2.SessionOrder IS NOT NULL THEN 1 ELSE 0 END [NewSearch]
    FROM    CTE T1
            LEFT JOIN CTE T2
                ON  T1.SessionID = T2.SessionID
                AND T1.Date = T2.Date
                AND T1.FirstTerm != T2.FirstTerm
                AND T1.SessionOrder = T2.SessionOrder + 1
)

次に、パーパスをグループ化するために、新しい検索ごとに、セッション内で独自のランクが必要です。次に、ルール (SessionID、日付、および最初の検索用語の一意の組み合わせ) を定義したら、フィルターの長さに応じて、一意の組み合わせ内で各アイテムを並べ替えることができます。

, CTE3 AS
(   SELECT  *,
            ROW_NUMBER() OVER(PARTITION BY SessionID, Date, ISNULL(SearchNumber, 0) ORDER BY LEN(Filter) DESC) [SearchOrder]
    FROM    CTE2 T1
            OUTER APPLY
            (   SELECT  SUM(NewSearch) [SearchNumber]
                FROM    CTE2 T2
                WHERE   T1.SessionOrder >= T2.SessionOrder
                AND     T1.SessionID = T2.SessionID
                AND     T1.Date = T2.Date
            ) c
)

最後に、SessionID、Date、および最初のフィルター用語の組み合わせごとに、結果を最長の検索用語に制限するだけです。

SELECT  ID, SessionID, Date, Filter
FROM    CTE3
WHERE   SearchOrder = 1
ORDER BY ID

通常、ここに完全に機能する例を投稿するのではなく、SQLFiddle にこれをすべてまとめますが、今日は機能していないようです。したがって、データをテストするために使用した完全な SQL は次のとおりです。

CREATE TABLE #Session (ID INT, SessionID VARCHAR(50), Date DATETIME, Filter VARCHAR(200))
INSERT INTO #Session VALUES
    (2, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'brand=Canon'),
    (4, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'meagPixel=5'),
    (6, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'brand=Canon'),
    (7, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'brand=Canon&meagPixel=12.1'),
    (8, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'brand=Canon'),
    (10, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'brand=Nikon'),
    (12, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'meagPixel=12.1'),
    (13, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:48', 'meagPixel=12.1&opticalZoom=True'),
    (14, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'meagPixel=12.1&opticalZoom=True&brand=Panasonic'),
    (16, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'price=500.00'),
    (18, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'price=499.00'),
    (19, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'price=499.00&brand=Olympus'),
    (21, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'zoomRange=2000'),
    (22, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'zoomRange=2000&brand=Leica'),
    (23, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'zoomRange=2000&brand=Leica&price=1995.00'),
    (24, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True'),
    (25, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:49', 'zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2'),
    (26, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:50', 'zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2&weight=345'),
    (27, 'peqq421gaspts3nuulq5mwcq', '24/05/2012 13:58', 'zoomRange=2000&brand=Leica&price=1995.00&opticalZoom=True&meagPixel=16.2'),
    (41, 'poiq41111spts00000q5aaaa', '27/05/2012 13:48', 'meagPixel=5')

;WITH CTE AS
(   SELECT  *, 
            SUBSTRING(Filter, 1, CASE WHEN CHARINDEX('&', Filter) = 0 THEN LEN(Filter) ELSE CHARINDEX('&', Filter) - 1 END) [FirstTerm],
    FROM    #Session
), CTE2 AS
(   SELECT  T1.*, 
            CASE WHEN T1.SessionOrder = 1 OR T2.SessionOrder IS NOT NULL THEN 1 ELSE 0 END [NewSearch]
    FROM    CTE T1
            LEFT JOIN CTE T2
                ON  T1.SessionID = T2.SessionID
                AND T1.Date = T2.Date
                AND T1.FirstTerm != T2.FirstTerm
                AND T1.SessionOrder = T2.SessionOrder + 1
), CTE3 AS
(   SELECT  *,
            ROW_NUMBER() OVER(PARTITION BY SessionID, Date, ISNULL(SearchNumber, 0) ORDER BY LEN(Filter) DESC) [SearchOrder]
    FROM    CTE2 T1
            OUTER APPLY
            (   SELECT  SUM(NewSearch) [SearchNumber]
                FROM    CTE2 T2
                WHERE   T1.SessionOrder >= T2.SessionOrder
                AND     T1.SessionID = T2.SessionID
                AND     T1.Date = T2.Date
            ) c
)
SELECT  ID, SessionID, Date, Filter
FROM    CTE3
WHERE   SearchOrder = 1
ORDER BY ID

DROP TABLE #Session

補遺

OK、実際には日付列でグループ化したくない結果セットに基づいて、最初の検索用語とセッション ID でグループ化された長さの順に行を配置するだけです。

このクエリは、サンプル データと同じ結果を生成します。2008 R1 でこれをテストしましたが、SQL-Server CE で機能しない理由はわかりません。

;WITH CTE AS
(   SELECT  *,
            ROW_NUMBER() OVER(PARTITION BY SessionID, SUBSTRING(Filter, 1, CASE WHEN CHARINDEX('&', Filter) = 0 THEN LEN(Filter) ELSE CHARINDEX('&', Filter) - 1 END) ORDER BY LEN(Filter) DESC) [RowNumber]
    FROM    Session
)
SELECT  *
FROM    CTE
WHERE   RowNumber = 1
ORDER BY ID

最終的なソリューションのSQL フィドル

于 2012-06-06T12:39:39.607 に答える
0

最長の検索フィルターを取得するには、次のようにする必要があります。

select s.*
from (select s.*,
             row_number() over (partition by sessionid order by len desc) as rownum
      from (select s.*, len(filter) as len
            from session s
           ) s
     ) s
where rownum = 1

私はWindows関数でこれをやっています。集計と結合を使用して同じことを行うことができます。

ただし、セッションは実際の識別子ではないと言っています。セッション/フィルターです。次のクエリは、必要なものをほとんど取得します。

select s.*
from (select s.*,
             row_number() overo over (partition by sessionid, filter 
                                      order by len desc) as rownum
      from (select s.*, len(filter) as len
            from session s
           ) s
     ) s
where rownum = 1

(唯一の変更点は、フィルターを含めるためのパーティショニング句です。)

重複している場合があります。すべての重複が必要な場合は、わずかに異なるクエリが機能します。

于 2012-06-06T12:14:50.283 に答える