0

这可能有点高级解释,因为这是我正在尝试做的一件非常复杂的事情(至少对我而言)。

我目前正在构建一个供个人在 PHP 和 MySQL 中使用的电影数据库,而 MySQL 部分正在杀死我。当前的设置是这样的:

我有一个包含名称、描述和值的主电影数据库,只有一个选项(如年份、年龄限制和媒体类型(DVD、蓝光等)。

我有额外的语言、字幕、音频格式等表格,它们都有两列。一个用于电影的 ID,另一个与索引匹配(例如语言 ID)。这些应该与主表连接在一起,并连接到一个字段中。

我的语言表示例:

movid | langid
--------------
1     | 2
1     | 4
2     | 4
3     | 5     

最理想的是,我想要这样的东西:

| ID | name    | description | year | subtitles | languages | audio |
--------------------------------------------------------------------
| 1  | One     | Bla bla     | 2010 | 2,3,5,6,7 | 3,6,22,6  | 10,5  |
| 2  | Another | foo bar     | 2008 | 6,33,5,27 | 10,4,2,3  | 8,15  |

可以将字幕和语言分解为 PHP 数组。这部分我实际上已经使用 GROUP_CONCAT 工作得很好,直到我需要搜索特定 subid 或 langid 的部分。这是我迄今为止一直在使用的查询。即使我还没有写出我所有的餐桌信息,我希望你能明白这一点:

SET SESSION group_concat_max_len = 512;

SELECT
movie.id,
movie.name,
movie.origname,
movie.`year`,
movie.`type`,
movie.duration,
movie.age,
GROUP_CONCAT(DISTINCT movie_language.langid ORDER BY langid) AS lang,
GROUP_CONCAT(DISTINCT movie_subtitles.subid ORDER BY subid) AS subtitles

FROM `movie`

LEFT JOIN `movie_audio` ON `movie`.`id`=`movie_audio`.`movid` 
LEFT JOIN `movie_company` ON `movie`.`id`=`movie_company`.`movid` 
LEFT JOIN `movie_genre` ON `movie`.`id`=`movie_genre`.`movid` 
LEFT JOIN `movie_language` ON `movie`.`id`=`movie_language`.`movid` 
LEFT JOIN `movie_subtitles` ON `movie`.`id`=`movie_subtitles`.`movid` 

GROUP BY movie.id

我使用 group_concat_max_len 来防止我获得 BLOB,到目前为止,我只尝试了 group_concatting 我的两个连接表(稍后将添加其余的表)。

这完全返回了我想要的内容,但是每个连接表只能有一个 WHERE 子句,否则它将返回 0 行。同样,如果我只搜索一个,它只会在 GROUP_CONCAT'ted 字段中返回搜索到的数字/ID。

然后我使用 IN() 函数对其进行了修复。至少我认为我做到了。但问题是它只适用于我所说的 OR 搜索。添加:

WHERE movie_subtitles.subid IN ()

没有在字幕表中的数字仍将返回该行,仅具有匹配的数字。这对于一半的搜索来说很好,但我也需要一种使用类似于 AND 的方法进行搜索的方法。

我不知道我是否需要完全重组,或者需要一个完全不同的查询,但我希望得到一些帮助或提示。

我也许应该说我也看过 HAVING 选项,但据我了解,它对我的​​查询无效。

顺便说一句,如果这是不可能的,我已经考虑废弃连接的表并将它们替换为在主电影表中易于搜索的字段(比如使用这个“语法”:'#2##4#',然后使用 LIKE '%#2#%' AND '%#4#%' 来匹配结果,或者作为最后的手段使用 PHP 对其进行排序(我宁愿死也不愿这样做),尽管我更喜欢它如果可以修复和使用上述解决方案)。

非常感谢您帮助我解决了头痛!

4

1 回答 1

0

子查询您的选择,然后您将更轻松地处理您的条款。

喜欢:

select *
   from (`your big query above`) as t
where subtitles regexp `your ids you want`
and lang regexp `your ids you want`

好吧,它并不完美,因为您的 id 将被转换为字符串(在 postgres 中,您有数组,因此您可以从顶层进行适当的搜索。)我不认为我真的想要使用正则表达式搜索 id。

那么,在最后一级之前不要连接你的 id 会更好。因此,您需要 3 个级别的查询:

select 
  stuff, ...
  group_concats
from
(
    select *
       from (`your big query above but without the group_concat`) as inner
    conditions ...

) as outer

编辑

尝试这个:

SELECT
id,
name,
origname,
`year`,
`type`,
duration,
age,

-- at this point we have the right rows we are just
-- grouping lang and subtitles
GROUP_CONCAT(DISTINCT langid ORDER BY langid) AS lang,
GROUP_CONCAT(DISTINCT subid ORDER BY subid) AS subtitles

from
(

    (
        SELECT
            movie.id,
            movie.name,
            movie.origname,
            movie.`year`,
            movie.`type`,
            movie.duration,
            movie.age,
            langid,
            subid


            FROM `movie`

            LEFT JOIN `movie_audio` ON `movie`.`id`=`movie_audio`.`movid`
            LEFT JOIN `movie_company` ON `movie`.`id`=`movie_company`.`movid`
            LEFT JOIN `movie_genre` ON `movie`.`id`=`movie_genre`.`movid`
            LEFT JOIN `movie_language` ON `movie`.`id`=`movie_language`.`movid`
            LEFT JOIN `movie_subtitles` ON `movie`.`id`=`movie_subtitles`.`movid`


            -- each row will have a different langid and different subid
            GROUP BY
                movie.id, langid, subid

    ) as inner

    -- you should be able to do any complex condition as this point
    where
        (langid = 1 or langid = 2)
        and (subid = 2 or subid = 3)

) as outer
于 2010-11-20T23:33:12.640 回答