3

テーブル内の他の値と一緒に、テーブル内の最大値を返すように計算しようとしています。ただし、これを実行しているテーブルは「実際の」テーブルではなく、サブクエリによって生成されたテーブルです。サブクエリ全体を再指定せずに2回参加することはできないと思うので、これは私に問題を与えます。

私は現在、を使用してこれに対するSQL Serverソリューションを持っていますROW_NUMBER() OVER (PARTITION BY providerId ORDER BY partnershipSetScore DESC) rnkが、この機能を持たないSqlite DBで実行されるプロジェクトの単体テストとして、可能であればDBMSに依存しないバージョンを探しています。

役立つ場合に備えて、スキーマとSQLServer固有のクエリを次に示します。

コース:

  • int id
  • varchar名
  • int schoolId

学校:

  • int id
  • varchar名

パートナーシップ:

  • int id
  • varcharpartnershipName

SchoolPartnership:

  • int id
  • int schoolId
  • intpartnershipId

クエリは次のとおりです。

SELECT
    schoolId,
    partnershipId AS bestPartnershipSetId,
    partnershipScore AS bestPartnershipScore
FROM
(
    SELECT
        pp.schoolId,
        partnershipScores.partnershipId,
        partnershipScores.partnershipScore,
        ROW_NUMBER() OVER (PARTITION BY schoolId ORDER BY partnershipScore DESC) rnk
    FROM schoolPartnership pp
    INNER JOIN (
        SELECT
            pp.partnershipId,
            (
                (CASE WHEN SUM(CASE WHEN c.name LIKE '%French%' THEN 1 ELSE 0 END) > 0 THEN 1 ELSE 0 END)
                + (CASE WHEN SUM(CASE WHEN c.name LIKE '%History%' THEN 1 ELSE 0 END) > 0 THEN 1 ELSE 0 END)
            ) AS partnershipScore
        FROM schoolPartnership pp
        INNER JOIN course c ON c.schoolId = pp.schoolId
        GROUP BY partnershipId
    ) AS partnershipScores ON partnershipScores.partnershipId = pp.partnershipId
) AS schoolPartnershipScores
WHERE rnk = 1

私が達成しようとしていることについてさらに情報が必要な場合は、大量のデータのカスタム並べ替えアルゴリズムを参照してください。このクエリは、最適なパートナーシップによる学校の並べ替えを実行する、より大きなクエリのサブクエリになります。

4

4 に答える 4

1

おそらく、サブクエリを 2 回結合することについて話しているとき、次のテクニックを念頭に置いていました。

SELECT a.*
FROM atable a
INNER JOIN (
  SELECT
    col1,
    MAX(col2) AS max_col2
  FROM atable
  GROUP BY col1
) m
ON a.col1 = m.col1 AND a.col2 = m.max_col2
;

そして、これが 1 つのテーブルに関するものであれば、DBMS に依存しない方法 (少なくとも、SQL Server と SQLite の両方で機能する方法) として使用してもまったく問題ありませんでした。

代わりに、サブクエリがあります。ただし、あなたが求めていることを達成する方法は他にありません。したがって、この状況では、2 つのオプションが表示されます (1 つは特定のケースでは適用できない可能性がありますが、一般的にはオプションです)。

  1. 回避しようとしていることを実行します。つまり、特にグループごとに集計された値を見つけるためにサブクエリを複製し、上記のように同じサブクエリに結合します。

  2. サブクエリの結果を一時的に永続化してから、上記の手法を一時的な結果セットに適用します。

最初のオプションは実際にはあまり魅力的ではありません。

2 番目のオプションの問題の 1 つは、一時データセットが SQL Server と SQLite で異なる方法で実装されることです。SQLite では、そのためにCREATE TEMPORARY TABLEステートメントを使用します。TEMPORARYSQL Server は、ステートメントのコンテキストでキーワードをサポートしていません。CREATE TABLE代わりに、テーブル名の先頭に特殊文字 ( #) を使用して、テーブルが実際には一時的なものであることを示します。

したがって、私が見ることができる唯一の回避策は、通常のテーブルを一時ストレージとして使用することです。一度作成してから、クエリを実行するたびに、一時的な結果セットを挿入する直前にその内容を削除できます。

DELETE FROM TempTable;
INSERT INTO TempTable (
  schoolId,
  bestPartnershipSetId,
  bestPartnershipScore
)
SELECT
  pp.schoolId,
  partnershipScores.partnershipId,
  partnershipScores.partnershipScore,
FROM
  ...
;
SELECT ...
FROM TempTable
...
;

または、クエリを実行するたびに作成してドロップすることもできます。

CREATE TABLE TempTable (
  ...
);
INSERT INTO TempTable (...)
SELECT ...
FROM ...
;
SELECT ...
FROM TempTable
...
;
DROP TABLE TempTable;

このように通常のテーブルを一時ストレージとして使用することは、SQL Server では同時実行に適していないことに注意してください。これが問題を引き起こす可能性がある場合は、おそらくこのオプションを放棄して、最初のオプションを選択する必要があります。(しかし、プラットフォームに依存しないソリューションが必要な場合、特に SQL Server と SQLite のようにプラットフォームが異なる場合は、おそらくこれが支払う必要があるコストです。)

于 2013-02-12T22:35:59.270 に答える
0

SQLにとらわれない最も方法は、「NONEXISTS」を使用することです。

SELECT * FROM schoolPartnership t1
WHERE NOT EXISTS 
       (SELECT * FROM schoolPartnership t2 
        WHERE t1.schoolId = t2.schoolId 
              AND t1.partnershipScore < t2.partnershipScore)

これにより、各schoolIdごとに最大partnershipScoreを持つschoolPartnershipからの行が得られます。

于 2013-02-12T21:34:26.437 に答える
0

私は解決策を見つけることができませんでした (回避しようとしていたサブクエリを複製する以外に)、PHP で各 PartnershipScore の MAX 行を特定し、他の行を破棄しました。理想的なソリューションではありませんが、クロスプラットフォームのアプローチが必要だったため、他に選択肢があまりありませんでした。

于 2013-02-18T22:43:28.210 に答える
0

これはあなたが望む構造です:

with t as (<subquery goes here>)
select t.*,
       max(col) over () as MaxVal
from t

ベースサブクエリが何であるかがわからないため、クエリにどのように適合するかを確認するのは少し難しいです。

サブクエリに複数回参加する場合は、SQL Server が「共通テーブル式」と呼ぶもの (with上記の句) を使用して実行できます。他の妥当なデータベースのほとんどはこれをサポートしています (MySQL と MS Access は 2 つの注目すべき例外から始まります)。

于 2013-02-12T20:54:36.317 に答える