2016-08-05 68 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

相關問題