0

我想使用表“相似”中的数据来查找表“发布”中的结果

表“相似”具有这种结构

artist  similar_artist
Moodymann   Theo Parrish
Moodymann   Jeff Mills
Moodymann   Marcellus Pittman
Moodymann   Rick Wilhite

到目前为止我的查询是

SELECT * FROM releases
WHERE 
releases.all_artists REGEXP 'Moodymann'
OR releases.label_no_country='KDJ'
OR releases.all_artists IN (SELECT similar_artist 
                            FROM similar 
                            WHERE artist='Moodymann')
ORDER BY date DESC

“all_artists”列有这样的记录:

Moodymann | Theo Parrish | Rick Wade
Jeff Mills | Moodymann | Rick Wilhite

所以我想要的最终查询基本上是这个

SELECT * FROM releases
    WHERE 
    releases.all_artists REGEXP 'Moodymann'
    OR releases.label_no_country='KDJ'
    OR releases.all_artists IN ('Theo Parrish','Jeff Mills','Marcellus Pittman','Rick Wilhite')

为了进行匹配,我认为我需要使用 REGEXP 而不是 IN - REGEXP 返回“子查询返回超过 1 行”。如何使用子查询返回的数据?

此外,查询需要很长时间才能运行(最多 20 秒) - 无论如何都可以加快速度,因为这在我的网络应用程序中不可用。

谢谢!

4

3 回答 3

4

我知道如何将 REGEXP 与子查询一起使用的唯一方法是使用该子查询来生成 REGEXP 字符串。

SELECT * FROM releases
WHERE 
releases.all_artists REGEXP 'Moodymann'
OR releases.label_no_country='KDJ'
OR releases.all_artists REGEXP (
   SELECT GROUP_CONCAT(similar_artist SEPARATOR '|') 
   FROM similar 
   WHERE artist='Moodymann' 
   GROUP BY similar_artist)
ORDER BY date DESC

以上内容未经测试,只是我可能尝试的理论。然而,它不会是非常理想的。

更新

此后对此进行了测试,发现GROUP BY similar_artist应该是GROUP BY artist

SELECT * FROM releases
WHERE 
releases.all_artists REGEXP 'Moodymann'
OR releases.label_no_country='KDJ'
OR releases.all_artists REGEXP (
   SELECT GROUP_CONCAT(similar_artist SEPARATOR '|') 
   FROM similar 
   WHERE artist='Moodymann' 
   GROUP BY artist)
ORDER BY date DESC

但是,正如 Pheonix 所提到的,您最好重构您的结构以拥有一个releases_artist表格。然后,您可以通过 JOIN 完成所有这些工作,这会快得多。

于 2013-06-03T08:09:02.497 回答
0

试试这个 SQL

SELECT * 
FROM releases
WHERE releases.all_artists LIKE '%Moodymann%'
OR releases.label_no_country='KDJ'
ORDER BY date DESC

SQL小提琴

MySQL 5.5.30 架构设置

CREATE TABLE Table1
    (`artist` varchar(9), `similar_artist` varchar(17))
;

INSERT INTO Table1
    (`artist`, `similar_artist`)
VALUES
    ('Moodymann', 'Theo Parrish'),
    ('Moodymann', 'Jeff Mills'),
    ('Moodymann', 'Marcellus Pittman'),
    ('Moodymann', 'Rick Wilhite')
;


create table allt(allf varchar(50));

insert into allt values('Moodymann | Theo Parrish | Rick Wade'),
('Jeff Mills | Moodymann | Rick Wilhite'),
('Jeff Mills | asdasdadasd | Rick Wilhite');

查询 1

SELECT * 
FROM allt
WHERE allt.allf LIKE '%Moodymann%'

结果

|                                  ALLF |
-----------------------------------------
|  Moodymann | Theo Parrish | Rick Wade |
| Jeff Mills | Moodymann | Rick Wilhite |
于 2013-06-03T07:57:47.343 回答
0

您可以在逗号分隔的列表上进行连接(不会很快,但可能比使用带前导通配符的 LIKE 更快),并且您可以用逗号替换现有的分隔符以允许这样做。您还可以使用大量的 UNION 来让您的艺术家列表表现得像一张表来进行连接。

此外,您可以使用 union 而不是其他 WHERE 子句,这可能有助于允许使用索引(MySQL 在查询中将只使用每个表的一个索引,因此使用 OR 来查询不同的列会强制它不使用索引对于它正在检查的列之一)。

因此,您可以执行以下操作:-

SELECT releases.* 
FROM releases
INNER JOIN (SELECT 'Theo Parrish' AS anArtist UNION SELECT 'Jeff Mills' UNION SELECT 'Marcellus Pittman' UNION SELECT 'Rick Wilhite') Sub1
ON FIND_IN_SET(Sub1.anArtist, REPLACE(releases.all_artists, " | ", ",")) > 0
UNION
SELECT releases.* 
FROM releases
WHERE releases.label_no_country='KDJ'

但是,如果更改数据库设计以将管道分隔的艺术家列表拆分到不同的表中甚至是一个轻微的选择,那么请改为这样做。它会更快,并且可以处理更多的艺术家。

于 2013-06-03T08:45:16.327 回答