我有两个表,一个电影表(mt,主表),以及一个列出这些电影可用的表(st,辅助表)。对于每个mt记录,有多个st记录。我需要一个将加入记录的查询,并允许我在两个表上运行查询。我目前使用这样的内连接:
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 st.title=@variable <> 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 :(得分: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,所以你需要命名选择列表的所有mt
列在GROUP BY
子句中。
重新发表您的第二条评论:
我想首先显示具有最近添加的相应st记录的mt行
如果使用分组功能,则可以向分组查询添加其他列。例如,每组date_added
的最新mt
为MAX(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;
答案 1 :(得分:0)
我认为你不需要这两个:
FROM mt AS mt
st AS st
和此:
INNER JOIN sttable AS st on mt.ID = st.ID