2009-11-25 71 views
2

我有兩個表,一個電影表(mt,主表)和一個表列出了這些電影可用的表(st,次表)。對於每個mt記錄,都有多個st記錄。我需要一個將加入記錄的查詢,並允許我在兩個表上運行查詢。我目前使用的內連接是這樣的:SQL邏輯:兩個表(分組?)

SELECT * FROM 
(
    SELECT ROW_NUMBER() OVER(ORDER BY " + orderField + @") AS RowNum, 
      mt.ID AS mt_ID, 
      mt.title AS mt_title, 
      [...] 
      st.ID AS st_ID, 
      st.title AS st_title, 
      [...] 
    FROM mt AS mt 
    st AS st 
    INNER JOIN sttable AS st on mt.ID =st.ID 
    WHERE [email protected] <> 0 AND mt.title = @variable 
)  
    as DerivedTableName 
    WHERE RowNum between 
    ((@pageIndex - 1) * @pageSize + 1) and @pageIndex*@pageSize 

這樣做的問題是,我需要通過使用ROWNUM和PageIndex的MT要能循環,並且查詢每部電影返回多個記錄(例如,如果某個特定電影有8個記錄,則返回8個,而不是1個)。我曾嘗試使用GROUP BY,但問題是它不會允許我對從屬表(st)中的字段執行查詢。

任何有關適當的邏輯的幫助將非常感激。

+0

不確定要了解您在那裏嘗試實現的目標。查詢返回所有具有相應mt和st的行。你想知道每個MT有多少記錄? – MPelletier 2009-11-25 00:15:51

回答

1

下面是做了GROUP BY派生表子查詢,所以你只能得到一個解決方案每個電影標題行,並從中計算出ROW_NUMBER()

然後在外部查詢中再次將派生表的結果加入st。每個電影標題仍會有多行,但RowNum將會重複,因此您可以正確篩選@pageIndex

SELECT * FROM 
(
    SELECT ROW_NUMBER() OVER(ORDER BY " + orderField + @") AS RowNum, 
      mt.ID AS mt_ID, 
      mt.title AS mt_title, 
      [...] 
    FROM mt AS mt 
    INNER JOIN sttable AS st ON mt.ID =st.ID 
    WHERE mt.title = @variable 
    GROUP BY mt.ID 
) mt1 
INNER JOIN sttable AS st1 ON (mt1.ID = st1.ID) 
WHERE mt1.RowNum BETWEEN 
    ((@pageIndex - 1) * @pageSize + 1) AND @pageIndex*@pageSize; 

你必須遍歷在你的顯示器的代碼外查詢的結果,並開始輸出的新行每當值RowNum變化。這是一個非常明顯的技術。

如果你不想做類似MySQL的GROUP_CONCAT()函數,這在Microsoft SQL Server中是非常棘手的(我假設你使用的是Microsoft)。

查看類似http://blog.shlomoid.com/2008/11/emulating-mysqls-groupconcat-function.html的博客,描述了使用FOR xml PATH ('')技巧。

PS:由於您的口頭描述,您的示例SQL查詢沒有意義,所以我盡我所能寫了一些合理的東西。無法保證它與您的模式相匹配。


回覆您的留言:我不認爲你需要子查詢中的任何st列訂購。我打算沒有包含在子查詢的選擇列表中的st列。在子查詢中加入st實例的唯一原因是將mt的行限制爲那些在st中具有匹配行的行。但GROUP BY mt.ID確保每行只有一行mt(實際上,因爲這是SQL Server,而不是MySQL,所以需要命名GROUP BY子句中的選擇列表的所有mt列)。


重新您的第二個評論:

我想有已經最近添加

您可以添加其他列分組對應的ST記錄第一顯示器MT行查詢您是否使用分組功能。例如,最新的date_added每組mtMAX(st.date_added),您可以將此列添加到子查詢中。

但是,請勿在子查詢中使用ORDER BY。有很少有任何理由來排序的子查詢,因爲順序可以通過使用子查詢結果無論如何改變了JOIN或其他操作你在使用子查詢

你應該在外部查詢排序:

SELECT * FROM 
(
    SELECT ROW_NUMBER() OVER(ORDER BY " + orderField + @") AS RowNum, 
      mt.ID AS mt_ID, 
      mt.title AS mt_title, 
      [...] -- other mt.* columns 
      MAX(st.date_added) AS latest_date_added 
    FROM mt AS mt 
    INNER JOIN sttable AS st ON mt.ID =st.ID 
    WHERE mt.title = @variable 
    GROUP BY mt.ID, -- other mt.* columns 
) mt1 
INNER JOIN sttable AS st1 ON (mt1.ID = st1.ID) 
WHERE mt1.RowNum BETWEEN 
    ((@pageIndex - 1) * @pageSize + 1) AND @pageIndex*@pageSize 
ORDER BY mt1.latest_date_added DESC, st1.date_added DESC; 
+0

謝謝你。我現在使用的查詢類似於你所建議的查詢,但是我遇到的問題是我需要能夠在內部查詢中對st進行排序,但是當我嘗試這樣做時,我被告知列I已選擇排序方式在選擇列表中無效,因爲它不包含在聚合函數或GROUP BY子句中。如果我將該列添加到GROUP BY子句中,則查詢再次開始爲每個mt條目返回多行。 – alpheus 2009-11-25 16:04:14

+0

確定 - 是的 - 我有mt列正常工作(它們在選擇列表和GROUP BY子句中),但是如何根據st中的字段進行排序?例如,我在st中有一個名爲「date_added」的字段,並且我想通過st.date_added命令mt結果(即,我想首先顯示具有最近添加的相應st記錄的mt行)。我會將ORDER BY st.date_added代碼放在外部查詢中嗎? – alpheus 2009-11-25 23:40:09

+0

Thansk非常。我得到了這個工作。 – alpheus 2009-11-30 22:49:58

0

我不認爲你需要有兩本:

FROM mt AS mt 
    st AS st 

這:

INNER JOIN sttable AS st on mt.ID = st.ID 
+0

不是一個答案,而是一個有效的評論。 – MPelletier 2009-11-25 00:50:14