0

我正在尝试在 CF/SQL 中做一些非常简单的事情,但似乎无法弄清楚我做错了什么。

我有这些表:

movies       genres     actors      moviesGenres     moviesActors
------       ------     ------      ------------     ------------
movieId      genreId    actorId     id               id
title        name       fname       movie            movie
                        lname       genre            actor

我正在尝试编写一个简单地列出所有电影的查询,其中包括每部电影的类型(可以多选)和每部电影的演员(同样,可以多选)。

当我编写查询以仅包含流派时,一切正常。我使用查询本身,按movieId分组,然后围绕流派单独分组。

但是当我尝试将演员包括在内时,一切都崩溃了,似乎分组崩溃了。

这是两个连接的 SQL 查询:

SELECT m.movieId, m.title, m.releaseDate, m.description, g.name, a.fname, a.lname
FROM movies m
   INNER JOIN genres g ON g.genreId IN (SELECT genre FROM moviesGenres WHERE movie = m.movieId)
   INNER JOIN actors a ON a.actorID IN (SELECT actor FROM moviesActors WHERE movie = m.movieId)
ORDER BY m.title

提前感谢您的帮助!

更新:

Leigh 和 Mark 提供的查询似乎总体上有效,但我仍然看到演员在 . 这是我的代码:

<tbody>
   <cfoutput query="variables.movieList" group="movieId">
      <tr>
         <td><a href="##">#title#</a></td>
         <td><cfoutput group="name">#name# | </cfoutput></td>
         <td><cfoutput group="actorId">#actorId# | </cfoutput></td>
      </tr>
   </cfoutput>
</tbody>

我也尝试过没有对最终标签进行分组,但这没有用。请注意,为了简化测试,我将 a.lName 和 a.fName 更改为 a.actorId。

示例行如下所示:

The Godfather    Action | Drama |    1 | 2 | 1 | 2 |
4

4 回答 4

3

您必须关联连接中的所有表。否则你会得到一个笛卡尔积。所以也要加入联结表,而不是在子查询中使用它们。使用正确的 ORDER BY,您应该能够根据需要<cfoutput group="..">来格式化输出。

没有经过测试,但有一些类似的东西。

SELECT m.movieId, m.title, m.releaseDate, m.description, g.name, a.actorID, a.fname, a.lname
FROM movies m
        LEFT JOIN moviesGenres mg ON mg.movie = m.movieID
        LEFT JOIN genres g ON g.genreID = mg.genre
        LEFT JOIN moviesActors ma ON ma.movie = m.movieID
        LEFT JOIN actors a ON a.actorId = ma.actor
// since movie names may not be unique, do a secondary sort on movieID
ORDER BY m.title, m.movieID, g.Name, a.fName, a.lName

根据评论编辑:

正如史蒂夫所提到的,在使用cfoutput group结果时,必须以相同的方式对结果进行排序和分组,才能使功能正常工作。有关更详细的解释,请参阅他的答案。

另一种方法是使用结构来生成独特的流派和演员。请注意,上面的 sql 查询稍作修改以匹配您更新的示例。

<table border="1">
<!--- group by ID in case multiple movies have the same name --->
<cfoutput query="yourQuery" group="movieID">

    <!--- use structures to save unique genres and actors --->
    <cfset genres = {}>
    <cfset actors = {}>
    <cfoutput>
        <cfset genres[name] = true>
        <cfset actors[actorID] = true>
    </cfoutput>

    <!--- display results --->
    <tr><td>#Title#</td>
        <td>#structKeyList(genres, "|")#</td>
        <td>#structKeyList(actors, "|") #</td>
    </tr>
</cfoutput>
</table>
于 2012-04-12T15:06:00.133 回答
2

不确定我喜欢你的语法。我猜你的子选择和别名正在搞砸你的结果。如果我发现你在做什么,你所追求的是加入这些桥牌桌。我会做这样的事情:

SELECT m.movieId, m.title, m.releaseDate, m.description, g.name, a.fname, a.lname
FROM movies m
  INNER JOIN movieGenres mg ON m.movieID = mg.movie
  INNER JOIN genres g ON g.genreID = mg.genre
  INNER JOIN movieactors ma on ma.movie  = m.movieID
  INNER JOIN actors a on ma.actor = a.actorID
ORDER BY m.title

如果actors.movi​​e 和genres.movi​​​​e都匹配movies.movi​​eID,这将起作用 - 但通常我希望看到比这更好的外键。例如,如果 Actor.movi​​​​e 确实包含“movieID”,则将其命名为“movieID” - 否则我想我正在寻找

于 2012-04-12T15:08:42.187 回答
2

您的问题确实有两个不同的问题。

1) 如何编写 SQL 查询来获取页面所需的结果。

Mark 和 Leigh 对这个问题都有很好的解决方案。我个人更喜欢Leigh的。

我将在您进行时添加转储您的结果(这里的所有人可能都知道,但是为后代记录是一件好事),因为很容易假设您得到的结果与您想象的不同。

此外,它与下一步特别相关。

2) 如何正确显示结果。

为此,您必须了解 cfoutput 的“组”属性是如何工作的。它只是检查您选择的列的值是否与上一行相比发生了变化。这意味着您必须按组列排序,否则分组将看起来错误。

例如:

类别,产品

  • 食品, 苹果
  • 清洁工,彗星
  • 食物,香蕉

如果您对上面的结果执行此操作,它看起来会出错,因为每次切换类别时都会显示分组输出。另一方面,以下结果集可以正常工作:

  • 清洁工,彗星
  • 食品, 苹果
  • 食物,香蕉

这样做的结果是 cfoutput 组取决于排序,因此您只能在任何一个级别的一列上使用它(当然,您可以根据需要深入任意级别)。

因此,解决方案是更手动地处理第二列分组。例如,这可以通过在某处建立一个列表然后循环遍历它。

因此,对于您示例中的查询,这将起作用:

<tbody>
   <cfoutput query="variables.movieList" group="movieId">
       <cfset actors = "">
        <cfoutput>
            <cfif NOT ListFindNoCase(actors,actorId)>
                <cfset actors = ListAppend(actors,actorId)>
            </cfif>
        </cfoutput>
      <tr>
         <td><a href="##">#title#</a></td>
         <td><cfoutput group="name">#name# | </cfoutput></td>
         <td><cfloop list="actors" index="actor">#actor# | </cfloop></td>
      </tr>
   </cfoutput>
</tbody>
于 2012-04-12T17:36:41.957 回答
0

您不能在同一个查询中同时使用演员和流派。最好的办法是只输出电影,<cfoutput query="someQry" group="movieId">然后进行查询以分别获取每部电影的演员和流派。

于 2012-04-12T15:19:33.897 回答