2017-10-10 78 views
1

我正在写一个简单的应用程序,订购我的媒体(图片,音乐,视频...)。每个媒体都可以与0到多个标签关联。 我的目标是建立一个可以搜索我的媒体的UI(例如,显示标记为%hol%的图像和视频,并返回假期标记的照片和好莱坞标记的照片)。限制加入和条件的sql查询结果

这里是我的数据库:

Table medias 
+---------+--------------+------+-----+---------+----------------+ 
| Field | Type   | Null | Key | Default | Extra   | 
+---------+--------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | NULL | auto_increment | 
| path | varchar(400) | NO | UNI | NULL |    | 
| type | varchar(5) | NO |  | NULL |    | 
| libelle | varchar(200) | NO |  | NULL |    | 
| ratings | int(2)  | NO |  | NULL |    | 
+---------+--------------+------+-----+---------+----------------+ 

Table tags 
+---------+--------------+------+-----+---------+----------------+ 
| Field | Type   | Null | Key | Default | Extra   | 
+---------+--------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | NULL | auto_increment | 
| libelle | varchar(200) | NO | UNI | NULL |    | 
+---------+--------------+------+-----+---------+----------------+ 

Table medias_tags 
+----------+---------+------+-----+---------+-------+ 
| Field | Type | Null | Key | Default | Extra | 
+----------+---------+------+-----+---------+-------+ 
| id_media | int(11) | NO | PRI | NULL |  | 
| id_tag | int(11) | NO | PRI | NULL |  | 
+----------+---------+------+-----+---------+-------+ 

因为我有很多媒体,我不得不限制的结果。所以在我的前端,我制作了一个分页系统,并根据我的页面查询我的媒体(例如,如果我在第3页上,我在我的sql语句中放置了LIMIT 20 OFFSET 60)。

现在我试图过滤我的媒体。我有一个搜索栏,如果我输入'hol',我想要20个媒体标记为'%hol%'(节假日,好莱坞...)

获得过滤媒体的作品,但我不知道如何获得20个媒体。

这里是我的SQL查询,而无需过滤:

SELECT 
medias.id, medias.path, medias.type, medias.libelle as libelle, medias.ratings, tags.libelle as tag 
FROM (select * from medias LIMIT ? OFFSET ?) medias 
left outer join medias_tags on medias.id = medias_tags.id_media 
left outer join tags on tags.id = medias_tags.id_tag 

这是我的筛选SQL查询:

SELECT 
medias.id, medias.path, medias.type, medias.libelle as libelle, medias.ratings, tags.libelle as tag 
FROM medias 
left outer join medias_tags on medias.id = medias_tags.id_media 
left outer join tags on tags.id = medias_tags.id_tag 
WHERE tags.libelle LIKE ? [OR tags.libelle LIKE ? ...] 

(最后一个参数是我的标签)

两个查询的工作很好,但我找不到限制我的过滤结果的方法。这里是我的筛选查询结果的一个样本:

+----+-------------+-------+-------------------+---------+------------+ 
| id | path  | type | libelle   | ratings | tag  | 
+----+-------------+-------+-------------------+---------+------------+ 
| 11 | mock/02.jpg | PHOTO | 02.jpg   |  0 | dark  | 
| 1 | mock/03.jpg | PHOTO | Purple   |  5 | wallpapper | 
| 3 | mock/01.jpg | PHOTO | Wave    |  5 | wave  | 
| 3 | mock/01.jpg | PHOTO | Wave    |  5 | wallpapper | 
+----+-------------+-------+-------------------+---------+------------+ 

如何限制我的过滤结果只返回n个不同的媒体ID?有没有纯粹的SQL解决方案?也许使用存储过程?

谢谢!

编辑:

这是我想用限= 7一样的结果:

+----+-------------+-------+-------------------+---------+------------+ 
| id | path  | type | libelle   | ratings | tag  | 
+----+-------------+-------+-------------------+---------+------------+ 
| 11 | mock/02.jpg | PHOTO | 02.jpg   |  0 | dark  | 
| 7 | mock/01.jpg | PHOTO | NEWLY ADDED MEDIA |  8 | wallpapper | 
| 2 | mock/02.jpg | PHOTO | Night    |  5 | wallpapper | 
| 2 | mock/02.jpg | PHOTO | Night    |  5 | dark  | 
| 1 | mock/03.jpg | PHOTO | Purple   |  5 | wallpapper | 
| 4 | mock/03.jpg | PHOTO | Purple 2   |  5 | wallpapper | 
| 5 | mock/03.jpg | PHOTO | Purple 3 EDITED |  8 | wallpapper | 
| 3 | mock/01.jpg | PHOTO | Wave    |  5 | wave  | 
| 3 | mock/01.jpg | PHOTO | Wave    |  5 | wallpapper | 
+----+-------------+-------+-------------------+---------+------------+ 

我有9行,但只有7 distincts媒体ID。每个媒体都有一个标签,如'%a%'。

编辑2:有人发布了答案,但删除了它。他的想法是连接标签,这也是一个很好的解决方案。

类似的东西:

+----+-------------+-------+-------------------+---------+------------+ 
| id | path  | type | libelle   | ratings | tag  | 
+----+-------------+-------+-------------------+---------+------------+ 
| 11 | mock/02.jpg | PHOTO | 02.jpg   |  0 | dark  | 
| 7 | mock/01.jpg | PHOTO | NEWLY ADDED MEDIA |  8 | wallpapper | 
| 2 | mock/02.jpg | PHOTO | Night    |  5 | wallpapper, dark | 
| 1 | mock/03.jpg | PHOTO | Purple   |  5 | wallpapper | 
| 4 | mock/03.jpg | PHOTO | Purple 2   |  5 | wallpapper | 
| 5 | mock/03.jpg | PHOTO | Purple 3 EDITED |  8 | wallpapper | 
| 3 | mock/01.jpg | PHOTO | Wave    |  5 | wave, wallpapper  | 
+----+-------------+-------+-------------------+---------+------------+ 

但我不知道该怎么写SQL查询...

+0

应用您限制条款本帖](https://stackoverflow.com/questions/13525656/limit-a-left-join-on-the-first-table)可能会有帮助。 – mseifert

+0

谢谢mseifert。我看过这篇文章,但似乎并没有解决我的问题。用于限制结果的子查询是我在第一次查询时使用的所有媒体,但它不适用于筛选结果,因为我试图限制表A,但我的条件是在连接表B上。 – Rylyn

+1

这个想法连接标签非常棒,使得查询更容易。 –

回答

1

使用GROUP_CONCAT可以为每个媒体构建一个标记字符串,并且外部联接此结果。然后根据需要

select 
    medias.id, 
    medias.path, 
    medias.type, 
    medias.libelle, 
    medias.ratings, 
    mtags.tags 
from medias 
left outer join 
(
    select id_media, group_concat(tags.libelle order by tags.libelle) as tags 
    from medias_tags 
    join tags on tags.id = medias_tags.id_tag 
    group by id_media 
) mtags on mtags.id_media = medias.id 
order by medias.id 
limit 20 offset 60; 
+0

它似乎工作完美,非常可读,谢谢! – Rylyn

0

你希望这样吗?

SELECT 
medias.id, medias.path, medias.type, medias.libelle as libelle, medias.ratings, tags.libelle as tag 
FROM medias 
left outer join medias_tags on medias.id = medias_tags.id_media 
left outer join tags on tags.id = medias_tags.id_tag 
WHERE tags.libelle LIKE ? [OR tags.libelle LIKE ? ...] 
order by medias.id 
limit 0,10 

这里限制用于前10条记录。您可以使用存储过程来传递限制的两个参数并选取已过滤的结果

+0

不幸的是,我得到了10条记录,而不是10个媒体。由于一些媒体有很多标签,因此在结果中返回的次数不止一次。播放此请求会返回10条记录,但只有4个媒体。不过谢谢! – Rylyn

+0

你可以分享你的预期结果演示吗? –

+1

当然,我编辑我原来的帖子,以添加预期的结果:) – Rylyn