SQL 하위 쿼리를 조인으로 변환하는 방법
-
03-07-2019 - |
문제
"Content"및 "Verseed-Content-Data"라는 1 : N 관계가있는 두 개의 테이블이 있습니다 (예 : 기사 엔티티 및 해당 기사의 모든 버전). 각 "컨텐츠"의 상단 버전을 표시하는보기를 만들고 싶습니다.
현재이 쿼리를 사용합니다 (간단한 하위 쿼리) :
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에서 나는 an을 만들려고했다 인덱싱 된보기 이 쿼리 중에서 하위 쿼리가 허용되지 않기 때문에 할 수없는 것 같습니다. 인덱스 뷰. 그래서 ... 여기 내 질문이 있습니다 ...이 쿼리를 조인으로 쿼리로 변환하는 방법을 생각할 수 있습니까?
인덱스 뷰는 다음을 포함 할 수없는 것 같습니다.
- 하위 쿼리
- 일반적인 테이블 표현
- 파생 된 테이블
- 조항이 있습니다
나는 필사적이다. 다른 아이디어는 환영합니다 :-)
정말 감사합니다!
해결책
테이블이 이미 제작 중이지만이를 모델링하는 올바른 방법은 버전 = 0을 영구 버전으로 만들고 항상 이전 자료의 버전을 증가시키는 것입니다. 따라서 새 버전을 삽입하면 다음과 같이 말할 것입니다.
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 (버전)를 선택할 필요가 없습니다.
다른 팁
아마도 이렇게?
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);
중
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
도움이 되었기를 바랍니다