17

次のフィールドを持つt1という名前のテーブルがあります:ROWID、CID、PID、Score、SortKey

次のデータがあります。

1, C1, P1, 10, 1
2, C1, P2, 20, 2
3, C1, P3, 30, 3

4, C2, P4, 20, 3
5, C2, P5, 30, 2

6, C3, P6, 10, 1
7, C3, P7, 20, 2

CIDでgroupbyを適用するようにどのクエリを記述しますか。ただし、グループごとに1つの結果を返す代わりに、グループごとに最大2つの結果を返します。また、条件がスコア> = 20であり、結果をCIDとSortKeyで並べ替えたい場合。

上記のデータに対してクエリを実行する必要がある場合、次の結果が期待されます。

C1の結果-注:ROWID 1は、スコア<20とは見なされません。

C1, P2, 20, 2
C1, P3, 30, 3

C2の結果-注:ROWID 5の値が小さいため、ROWID5はROWID4の前に表示されますSortKey

C2, P5, 30, 2
C2, P4, 20, 3

C3の結果-注:ROWID 6は、スコアが20未満であるため表示されないため、ここに返されるレコードは1つだけです。

C3, P7, 20, 2

短期的には、GROUPBY内の制限が必要です。私は最も単純な解決策が必要であり、一時テーブルを避けたいと思っています。サブクエリは問題ありません。また、これにはSQLiteを使用していることに注意してください。

4

5 に答える 5

13

必要なことを行うためのかなり移植可能なクエリを次に示します。

SELECT *
FROM table1 a 
WHERE a."ROWID" IN (
    SELECT b."ROWID" 
    FROM table1 b 
    WHERE b."Score" >= 20 
      AND b."ROWID" IS NOT NULL 
      AND a."CID" = b."CID" 
    ORDER BY b."CID", b."SortKey" 
    LIMIT 2
)
ORDER BY a."CID", a."SortKey";

クエリは、並べ替えと制限を伴う相関サブクエリを使用してROWID、最終結果に表示される のリストを生成します。相関サブクエリはすべての行に対して実行されるため、結果に含まれているかどうかに関係なく、以下に示すウィンドウ関数のバージョンほど効率的ではない可能性がありますが、そのバージョンとは異なり、ウィンドウをサポートしていない SQLite3 で動作します。機能。

このクエリでは、ROWID一意である必要があります (主キーとして使用できます)。

上記を PostgreSQL 9.2 および SQLite3 3.7.11 でテストしました。両方で正常に動作します。LIMITMySQL はで使用されるサブクエリをサポートしていないため、MySQL 5.5 または最新の 5.6 マイルストーンでは機能しませんIN

SQLFiddle デモ:

  • PostgreSQL (正常に動作します): http://sqlfiddle.com/#!12/22829/3

  • SQLite3 (正常に動作し、同じクエリ テキストですが、明らかな JDBC ドライバーの制限により、単一値の挿入が必要です): http://sqlfiddle.com/#!7/9ecd8/1

  • MySQL 5.5 (2 つの方法で失敗します。MySQL はモードa."ROWID"でもANSI引用符を付けたくないので、引用符を外さなければなりませんでした。その後、で失敗しますThis version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery): http://sqlfiddle.com/#!2/e1f31/2

SQLite3 コマンドラインで問題なく動作することを示す SQLite デモ: http://pastebin.com/26n4NiUC

出力 (PostgreSQL):

 ROWID | CID | PID | Score | SortKey 
-------+-----+-----+-------+---------
     2 | C1  | P2  |    20 |       2
     3 | C1  | P3  |    30 |       3
     5 | C2  | P5  |    30 |       2
     4 | C2  | P4  |    20 |       3
     7 | C3  | P7  |    20 |       2
(5 rows)

特定の をフィルタリングする場合は、外側の句に or をCID追加するだけです。AND "CID" = 'C1' WHERE

より詳細な例を含む密接に関連する回答を次に示します: https://stackoverflow.com/a/13411138/398670


これはもともとSQL(SQLiteなしで)タグ付けされていたので...完全を期すために、PostgreSQLまたはSQL標準ウィンドウ関数をサポートする他のDBでは、おそらくこれを行うでしょう:

SELECT "ROWID", "CID", "PID", "Score", "SortKey"
FROM (
  SELECT *, row_number() OVER (PARTITION BY "CID" ORDER BY "SortKey") AS n
  FROM table1
  WHERE "Score" >= 20
) x
WHERE n < 3
ORDER BY "CID", "SortKey";

同じ結果が得られます。C1制限フィルターが実際に機能することを示す追加の行を含む SQLFiddle : http://sqlfiddle.com/#!12/22829/1

特定の をフィルタリングしたい場合は、内側の節に or をCID追加するだけです。AND "CID" = 'C1' WHERE


ところで、スコアが 20 を超える CID に対して 2 行を超えることはできないため、テスト データは不十分です。

于 2012-11-16T06:00:30.743 に答える
4

これは実際にはGROUP BY問題ではありません (値を集計していません)。greatest-n-per-groupこれは、グループあたり最大 n の問題です (実際、ここ Stackoverflow にタグがあると思います)。

ソリューションの正確な詳細は、グループごとに同じ並べ替えキーが 2 回あるかどうかなどの問題によって異なります。次のようなものから始めることができます。

SELECT * FROM table T1 WHERE Score > 20 AND
  (SELECT COUNT(*) FROM table T2 
      WHERE T2.CID = T1.CID AND T2.SortKey <= T1.SortKey AND T2.RowID <> T1.RowID
        AND T1.Score > 20) < 2;
  ORDER BY CID, SortKey;

これが行うことは、スコアが 20 を超える行のみを考慮することです。次に、各候補行について、スコアが 20 を超えているが、ソートキーがこの行のソートキー以下である、同じテーブル内の他の行の数をカウントします。その数が 0 または 1 行の場合、この行は結果に含める資格があります。

最後に ORDER by がソートを実行します。

于 2011-10-22T03:17:51.780 に答える
0

MySQL

SELECT  l.*
FROM    (
        SELECT  cid,
                COALESCE(
                (
                SELECT  id
                FROM    mytable li
                WHERE   li.cid = dlo.cid
                        AND li.score >= 20
                ORDER BY
                        li.cid, li.id
                LIMIT 1, 1
                ), CAST(0xFFFFFFFF AS DECIMAL)) AS mid
        FROM    (
                SELECT  DISTINCT cid
                FROM    mytable dl
                ) dlo
        ) lo, mytable l
WHERE   l.cid >= lo.cid
        AND l.cid <= lo.cid
        AND l.id <= lo.mid
        AND l.score >= 20
于 2009-04-15T12:07:51.433 に答える
-1

**のような単純なものではないでしょうか

SELECT CID, PID, Score, SortKey
FROM T1
WHERE score >= 20
ORDER BY CID, Sortkey

**

または私は何かを逃していますか?

于 2009-04-15T12:19:14.213 に答える
-4

SQLite では LIMIT 句を使用できます。例えば ​​:

select * from tableName where field1='something' limit 10;

これにより、最初の 10 行が得られます。

于 2011-06-02T14:14:15.237 に答える