2009-03-02 66 views
8

我有兩個1:n關係的表:「content」和「versioned-content-data」(例如,文章實體和該文章創建的所有版本) 。我想創建一個顯示每個「內容」的頂級版本的視圖。如何將SQL子查詢轉換爲連接

目前我使用此查詢(用一個簡單的子查詢):

 
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中我試圖創建這個查詢的索引視圖但似乎我不能因爲子查詢不索引視圖允許的。所以...這是我的問題...你能想出一種方法來將這個查詢轉換成JOINs的某種查詢嗎?

好像索引視圖不能包含:

  • 子查詢
  • 公用表表達式
  • 派生表
  • HAVING子句

我絕望。任何其他想法都歡迎:-)

非常感謝!

+0

是你的子查詢是否正確?我只看到一個表,引用 – 2009-03-02 01:00:33

+0

是的,是同一個表的子查詢,提取共享相同的fk_idothertable – sachaa 2009-03-02 01:02:20

+0

btw ...的項目的最大版本... fk_idothertable是主表的外鍵 – sachaa 2009-03-02 01:05:05

回答

13

這可能不會如果表格已經投入生產,那麼這個模型的正確方法是讓版本= 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聚集。你總是知道當前版本是什麼。您無需選擇max(版本)即可插入新記錄。

-1

像這樣......我假設子查詢中的'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 

希望這有助於

+0

子查詢實際上是對提取特定項目的最高版本的同一張表的查詢。請注意,相同的版本化項目將具有相同的fk_idothertable。 – sachaa 2009-03-02 01:19:08

0

我不知道如何有效的,這將是,但:

 
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 
0

你也許能夠使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 
3

也許這樣的事情?

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) 

只是胡亂猜測......

0

我覺得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); 

中號

0
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).