SQL JOIN并在第二个表中限制某些条件的结果

时间:2017-08-17 08:34:27

标签: sql postgresql

我有两张桌子。

公文包:

+----+-------+--------------+
| id | name  | created_date |
+----+-------+--------------+
| 1  | Port 1| 2017/08/12   |
+----+-------+--------------+
| 2  | Port 2| 2017/08/14   |
+----+-------+--------------+
| 3  | Port 3| 2017/08/15   |
+----+-------+--------------+

照片

+----+------------+--------------+--------------+-----------------+
| id | Port_name  | port_id    | user_id    | created_at      |
+----+------------+--------------+--------------+-----------------+
| 1  | Port 1     |          1   |       null   |    2017/08/10   |
+----+------------+--------------+--------------+-----------------+
| 2  | Port 2     |          2   |       null   |    2017/08/11   | 
+----+------------+--------------+--------------+-----------------+
| 3  | Port 3     |          3   |       null   |    2017/08/12   |
+----+------------+--------------+--------------+-----------------+
| 4  | Port 1     |          1   |          1   |    2017/08/13   | 
+----+------------+--------------+--------------+-----------------+
| 5  | Port 2     |          2   |          1   |    2017/08/14   |
+----+------------+--------------+--------------+-----------------+
| 6  | Port 3     |          3   |          1   |    2017/08/15   | 
+----+------------+--------------+--------------+-----------------+
| 7  | Port 2     |          2   |          1   |    2017/08/16   |
+----+------------+--------------+--------------+-----------------+
| 8  | Port 3     |          3   |          1   |    2017/08/17   |
+----+------------+--------------+--------------+-----------------+
| 9  | Port 2     |          2   |          1   |    2017/08/18   |
+----+------------+--------------+--------------+-----------------+
|10  | Port 3     |          3   |          1   |    2017/08/19   |
+----+------------+--------------+--------------+-----------------+

如何查询以获得如下结果:

结果:

+---------+------------+----------------+-----------------+
| Port_id | port_name  | photo_id       | photo_created_at|
+---------+------------+----------------+-----------------+
| 2       | Port 2     |       7        |    2017/08/16   | 
+---------+------------+----------------+-----------------+
| 3       | Port 3     |       8        |    2017/08/17   |
+---------+------------+----------------+-----------------+

我想要做的是将投资组合表加入照片表,并在某些条件下限制照片表的结果:

  1. user_id不为空
  2. created_at是“第二古老的”
  3. “第二古老”的意思是,例如,我有4个日期时间: 2017/08/112017/08/122017/08/162017/08/19

    在这种情况下,“第二个最旧的”是2017/08/12

    我自己尝试过:

    SELECT p.id as Port_id, 
           p.name as Port_name, 
           ph.id as photo_id, 
           ph.created_at as photo_created_at 
    FROM "Portfolios" AS p
    LEFT JOIN (
              SELECT * 
              FROM "Photos" 
              WHERE user_id IS NOT NULL 
              ORDER BY created_at ASC 
              LIMIT 1 OFFSET 1) as ph
    ON p.id = ph.port_id;
    

    并用Google搜索,但没有找到解决我问题的方法。

    有任何帮助吗? 谢谢你的进步!

2 个答案:

答案 0 :(得分:1)

我使用了两个GROUP BY构造。我省略了Portfolios表,因为它似乎并不重要

select photos.port_id, min(photos.id), min(photos.created_at)
from photos
join 
(
  select port_id, min(created_at) photos_ca_min
  from photos
  where user_id is not null
  group by port_id
) p on p.port_id = photos.port_id
where photos.created_at > p.photos_ca_min and user_id is not null
group by photos.port_id

SQLFiddle

答案 1 :(得分:1)

像Radim一样,我不理解加入投资组合的必要性,因为这没有任何作用。我的解决方案使用row_number()函数:

SELECT port_id, port_name, id as photo_id, created_at as photo_created_at FROM
(select *, row_number() OVER (PARTITION BY port_id ORDER By created_at) AS rn from 
photos WHERE user_id IS NOT NULL) r
WHERE r.rn = 2

但是,如果在照片中没有重复port_name,那么链接到投资组合会有意义!从理论上讲,port_name不应该在照片中!

修改

如果您从照片中删除port_name,则需要:

SELECT r.port_id, p.port_name, r.id as photo_id, r.created_at as photo_created_at FROM
(select *, row_number() OVER (PARTITION BY port_id ORDER By created_at) AS rn from 
photos WHERE user_id IS NOT NULL) r INNER JOIN portfolios p on p.id = r.port_id
WHERE r.rn = 2