2

次のスキーマを持つ2つのテーブルがあります。

表A

usernName, email (one email per user)

表B

userName, product (many products per user)

userName + email製品の数が最も多い10人のユーザー、中間の10人のユーザー、および製品の数が最も少ない10人のユーザーを返すクエリを作成したいと思います。

30を超えるレコードがあることを事前に確認します(重複を避けるため)

私はgroupby私を助けないことを知っています。ランクを使用する必要がありpartitionbyますか?groupbyとの違いは何partitionbyですか?

これはどのように書くべきですか?

4

2 に答える 2

4
SELECT  userName, email
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (ORDER BY products DESC) rn,
                COUNT(*) OVER () AS cnt
        FROM    (
                SELECT  userName, email, products
                FROM    a
                CROSS APPLY
                        (
                        SELECT  COUNT(*) products        
                        FROM    b
                        WHERE   b.userName = a.userName
                        ) p
                )
        ) q
WHERE   rn <= 10
        OR
        rn >= cnt - 10
        OR
        rn BETWEEN cnt / 2 - 5 AND cnt / 2 + 4
于 2012-05-20T07:32:18.957 に答える
1

以下は、 @ Quassnoiの提案と論理的に同等である必要がありますが、簡単にパラメータ化できるように構築されてい10ます(以下に置き換えられ@cntます)。

SELECT
  userName,
  email
FROM (
  SELECT
    A.userName,
    A.email,
    rnAsc    = ROW_NUMBER() OVER (ORDER BY COUNT(*) ASC),
    rnDesc   = ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC)
  FROM A
    INNER JOIN B ON A.userName = B.userName
  GROUP BY
    A.userName,
    A.email
) s
WHERE rnAsc  <= @cnt
   OR rnDesc <= @cnt
   OR rnAsc - rnDesc BETWEEN -@cnt AND @cnt - 1
;
于 2012-05-20T17:48:15.153 に答える