2016-08-05 29 views
2

我正在使用的应用程序包含用户可以创建相册并将图像上传到其中的部分。该应用程序创建图像的几个大小,以便大型版本不会提供给用户。有关文件的所有信息都被存储在数据库中的结构如下如何指定GROUP BY保留哪些行以及哪些行应该折叠

  1. 专辑表有一个ID和名称
  2. 照片表有照片的列表和他们每个人都知道它是属于
  3. 什么专辑还有一个photo_versions。每个photo_versions存储Photo表格中对象的ID。

这个逻辑是由下面的模式表示:

CREATE TABLE albums(`id` int, `name` varchar(255)); 
INSERT INTO albums (id, name) VALUES 
(1, "one"), 
(2, "two"), 
(3, "three"); 

CREATE TABLE photos(`id` int, `albums_id` int, `title` varchar(255)); 
INSERT INTO photos (id, albums_id, title) VALUES 
(1, 1, "a"), 
(2, 1, "b"), 
(3, 1, "c"); 

CREATE TABLE photos_versions(`id` int, `photos_id` int, `width` int, `height` int); 
INSERT INTO photos_versions (photos_id, width, height) VALUES 
(1, 1000, 800),(1, 800, 600), (1, 600, 400), 
(2, 1000, 800), (2, 800, 600), (2, 600, 400), 
(3, 1000, 800), (3, 800, 600), (3, 600, 400); 

用户界面请求特定的高度和我的工作应该返回最接近的现有数据库后端的能力。我正在努力应该这样做。它与加入所有这些表开始:

SELECT * 
FROM albums a 
INNER JOIN photos p ON p.albums_id = a.id 
INNER JOIN photos_versions pv ON pv.photos_id = p.id; 

这导致如下表所示:

+------+------+----+-----------+-------+------+-----------+-------+--------+ 
| id | name | id | albums_id | title | id | photos_id | width | height | 
+------+------+----+-----------+-------+------+-----------+-------+--------+ 
| 1 | one | 1 |   1 | a  | NULL |   1 | 1000 | 800 | 
| 1 | one | 1 |   1 | a  | NULL |   1 | 800 | 600 | 
| 1 | one | 1 |   1 | a  | NULL |   1 | 600 | 400 | 
| 1 | one | 2 |   1 | b  | NULL |   2 | 1000 | 800 | 
| 1 | one | 2 |   1 | b  | NULL |   2 | 800 | 600 | 
| 1 | one | 2 |   1 | b  | NULL |   2 | 600 | 400 | 
| 1 | one | 3 |   1 | c  | NULL |   3 | 1000 | 800 | 
| 1 | one | 3 |   1 | c  | NULL |   3 | 800 | 600 | 
| 1 | one | 3 |   1 | c  | NULL |   3 | 600 | 400 | 
+------+------+----+-----------+-------+------+-----------+-------+--------+ 
9 rows in set (0.00 sec) 

现在,我们需要组由photos_id(因为我们想给出的最接近的版本落得照片)。因此,请求转成:

SELECT * 
FROM albums a 
INNER JOIN photos p ON p.albums_id = a.id 
INNER JOIN photos_versions pv ON pv.photos_id = p.id 
GROUP BY photos_id; 

导致如下表所示:

+------+------+----+-----------+-------+------+-----------+-------+--------+ 
| id | name | id | albums_id | title | id | photos_id | width | height | 
+------+------+----+-----------+-------+------+-----------+-------+--------+ 
| 1 | one | 1 |   1 | a  | NULL |   1 | 1000 | 800 | 
| 1 | one | 2 |   1 | b  | NULL |   2 | 1000 | 800 | 
| 1 | one | 3 |   1 | c  | NULL |   3 | 1000 | 800 | 
+------+------+------+-----------+-------+------+-----------+-------+--------+ 
3 rows in set (0.00 sec) 

然而,这并不一定保持该行与属性(其最接近的一个我的高度指定)。我如何将photos_id分组并选择最接近身高的人?

P.S. SQL小提琴附加 - http://sqlfiddle.com/#!9/84f4f/1

+1

什么决定应该返回哪一行?你在哪里指定查询中的“高度”? – sgeddes

+0

@sgeddes我不这样做,这是我的问题是问 –

回答

1

这里的一种方法是添加一个额外的连接到您的查询,这将限制到每个照片ID组具有最接近的高度的照片。

SELECT a.*, p.*, pv1.* 
FROM albums a 
INNER JOIN photos p 
    ON p.albums_id = a.id 
INNER JOIN photos_versions pv1 
    ON pv1.photos_id = p.id 
INNER JOIN 
(
    SELECT photos_id, MIN(ABS(height - SOME_HEIGHT)) AS diff 
    FROM photos_versions 
    GROUP BY photos_id 
) pv2 
    ON pv1.photos_id = pv2.photos_id AND 
     MIN(ABS(pv1.height - SOME_HEIGHT)) = pv2.diff 

您可以用您通过高度搜索获得的任何值替换SOME_HEIGHT

相关问题