SQLサブクエリを結合に変換する方法
-
03-07-2019 - |
質問
1:nの関係を持つ2つのテーブル:" content"および「バージョン付きコンテンツデータ」 (たとえば、記事のエンティティとその記事で作成されたすべてのバージョン)。各" content"のトップバージョンを表示するビューを作成したいと思います。
現在、このクエリを使用します(単純なサブクエリを使用):
SELECT t1.id, t1.title, t1.contenttext, t1.fk_idothertable t1.version FROM mytable as t1 WHERE (version = (SELECT MAX(version) AS topversion FROM mytable WHERE (fk_idothertable = t1.fk_idothertable)))
サブクエリは、実際には特定のアイテムの最高バージョンを抽出する同じテーブルへのクエリです。バージョン管理されたアイテムには同じfk_idothertableがあることに注意してください。
SQL Serverでは、このクエリのインデックス付きビューを作成しようとしましたが、インデックス付きビューではサブクエリが許可されていないため、できないようです。それで...ここに私の質問があります...このクエリをJOINで何らかのクエリに変換する方法を考えていただけますか?
インデックス付きビューには以下を含めることはできないようです:
- サブクエリ
- 共通テーブル式
- 派生テーブル
- HAVING句
私は必死です。他のアイデアは大歓迎です:-)
どうもありがとう!
解決
テーブルがすでに実稼働している場合、これはおそらく役に立ちませんが、これをモデル化する正しい方法は、バージョン= 0を永続的なバージョンにし、常にOLDERマテリアルのバージョンをインクリメントすることです。したがって、新しいバージョンを挿入すると、次のようになります。
UPDATE thetable SET version = version + 1 WHERE id = :id
INSERT INTO thetable (id, version, title, ...) VALUES (:id, 0, :title, ...)
このクエリは次のようになります
SELECT id, title, ... FROM thetable WHERE version = 0
サブクエリなし、MAX集約なし。あなたは常に現在のバージョンが何であるかを知っています。新しいレコードを挿入するためにmax(version)を選択する必要はありません。
他のヒント
おそらくこのようなものですか?
SELECT
t2.id,
t2.title,
t2.contenttext,
t2.fk_idothertable,
t2.version
FROM mytable t1, mytable t2
WHERE t1.fk_idothertable == t2.fk_idothertable
GROUP BY t2.fk_idothertable, t2.version
HAVING t2.version=MAX(t1.version)
ごく当たり前の推測...
MAXをグループ化するテーブルエイリアスにすることができる場合があります。
次のようになります:
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1 JOIN
(SELECT fk_idothertable, MAX(version) AS topversion
FROM mytable
GROUP BY fk_idothertable) as t2
ON t1.version = t2.topversion
FerranBは近いと思いますが、グループ化の権利がありませんでした:
with
latest_versions as (
select
max(version) as latest_version,
fk_idothertable
from
mytable
group by
fk_idothertable
)
select
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable,
t1.version
from
mytable as t1
join latest_versions on (t1.version = latest_versions.latest_version
and t1.fk_idothertable = latest_versions.fk_idothertable);
M
If SQL Server accepts LIMIT clause, I think the following should work:
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1 ordery by t1.version DESC LIMIT 1;
(DESC - For descending sort; LIMIT 1 chooses only the first row and
DBMS usually does good optimization on seeing LIMIT).
これがどれほど効率的かはわかりませんが、:
SELECT t1.*, t2.version FROM mytable AS t1 JOIN ( SElECT mytable.fk_idothertable, MAX(mytable.version) AS version FROM mytable ) t2 ON t1.fk_idothertable = t2.fk_idothertable
これと同じように...サブクエリの「mytable」は実際のテーブルとは異なると仮定しています...そのため、mytable2と呼びました。同じテーブルであれば、これはまだ機能しますが、fk_idothertableは 'id'になるだけだと思います。
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1
INNER JOIN (SELECT MAX(Version) AS topversion,fk_idothertable FROM mytable2 GROUP BY fk_idothertable) t2
ON t1.id = t2.fk_idothertable AND t1.version = t2.topversion
これが役立つことを願って