2015-12-05 32 views
0

我想写一个非常复杂的SQL查询。要求如下:复杂的MySQL查询问题和SQL挂起

我需要从查询返回这些字段:

track.artist 
track.title 
track.seconds 
track.track_id 
track.relative_file 
album.image_file 
album.album 
album.album_id 
track.track_number 

我可以选择一个随机曲目用下面的查询:

select 
    track.artist, track.title, track.seconds, track.track_id, 
    track.relative_file, album.image_file, album.album, 
    album.album_id, track.track_number 
FROM 
    track, album 
WHERE 
    album.album_id = track.album_id 
ORDER BY RAND() limit 10; 

下面是我在哪里虽然有麻烦。我也有一个名为“trackfilters1”到“trackfilters10”的表格。每行都有一个自动递增的ID字段。因此,第10行是album_id 10的数据。这些字段填充1和0。例如,专辑#10有10首曲目,如果所有曲目都包含在搜索中,则trackfilters1.flags将包含“1111111111”。如果轨道10被排除,那么它将包含“1111111110”

我的问题是包括这个条款。

我已经拿出了最新的查询如下:

select 
    track.artist, track.title, track.seconds, 
    track.track_id, track.relative_file, album.image_file, 
    album.album, album.album_id, track.track_number 
FROM 
    track, album, trackfilters1, trackfilters2 
WHERE 
    album.album_id = track.album_id 
AND 
    ((album.album_id = trackfilters1.id) 
OR 
    (album.album_id=trackfilters2.id)) 
AND 
    ((mid(trackfilters1.flags, track.track_number,1) = 1) 
OR 
    (mid(trackfilters2.flags, track.track_number,1) = 1)) 
ORDER BY RAND() limit 2; 

然而,这导致SQL挂起。我假设我做错了什么。有人知道它是什么吗?如果有更简单的方法来实现我的最终结果,我会接受建议,如果有更好的方法来完成此操作,我不会修复已损坏的查询。

另外,在我的试验中,我注意到当我有一个工作查询并且在FROM子句中添加了说,trackfilters2而没有在查询中的任何地方使用它时,它也会挂起。这让我感到惊讶。这是正确的行为?我想如果不使用这些数据就可以添加到FROM列表中,只会让服务器获得更多的数据,我不会期望它挂起。

+0

_“那么trackfilters1.flags将包含”1111111111“,如果所有曲目将包含在搜索中。如果轨道10被排除,那么它将包含“1111111110”“_ - 这听起来像是一个非常糟糕的数据库设计。你应该正常化。 – CBroe

+0

这是因为当你只使用逗号分开的两个表时,你正在做交叉产品,即一个表的每一行与另一个表的每一行连接。因此,当你包含trackfilters2,但不在where子句中使用它,你的系统最终会因为交叉产品而挂起 – Naruto

+0

也许我可以看看一些数学计算。我有一个想法做一些类似于CHMOD的数字在Linux中,你可以使用一个3位数字来确定9个位置,可能有三个状态之一(rwxrwxrwx),但认为这将是一个更合理的方法,因为我可以使用MID在查询内拉出轨道号的位置。我想知道这是否与你的建议相似。我现在将阅读正常化。感谢您的回复 –

回答

0

这里没有足够的信息来确定导致性能问题的原因。

但是,这里有一些建议和意见。

抛弃连接操作的旧式逗号语法,并改为使用JOIN关键字。并将连接谓词重定位到ON子句。

为了天堂的缘故,请格式化SQL,使其可以被试图阅读的人识破。

这里有一些问题......在你想要返回的行中,trackfilters1和trackfilters2中总会有匹配的行吗?或者trackfilters2中可能缺少一行,并且如果trackfilters1中存在匹配的行,您仍然希望返回该行? (这个问题的答案决定了你是否希望使用外连接和内连接来处理这些表。)

为了获得大集合的最佳性能,定义合适的索引将非常关键。

使用EXPLAIN查看执行计划。

我建议你尝试写你的查询是这样的:

SELECT track.artist 
     , track.title 
     , track.seconds 
     , track.track_id 
     , track.relative_file 
     , album.image_file 
     , album.album 
     , album.album_id 
     , track.track_number 
    FROM track 
    JOIN album 
     ON album.album_id = track.album_id 
    LEFT 
    JOIN trackfilters1 
     ON trackfilters1.id = album.album_id 
    LEFT 
    JOIN trackfilters2 
     ON trackfilters2.id = album.album_id 
    WHERE MID(trackfilters1.flags, track.track_number, 1) = '1' 
     OR MID(trackfilters2.flags, track.track_number, 1) = '1' 
    ORDER BY RAND() 
    LIMIT 2 

如果你想与性能方面提供帮助,提供从EXPLAIN输出,什么指标来定义。

+0

我很欣赏你写这个回复的时间。我有很多东西要学习连接,内部和外部等。我已经决定采用不同的方法,我将在TRACK表中为每个条目设置一个“filterflags”列,它将是10位数字(一个用于每个轨道过滤器列表)从这里,我将能够轻松地检查中间(filterflags,x,1)为1或0在我的查询内,并且可以做我的查询。我会回到这个帖子来记录你的建议并试图理解它们。我会接受你的解决,因为你花时间写这个。谢谢大家。 –