2014-12-19 26 views
0

选择最后更改的行我有一个表产品子查询

id | owner_id | last_activity | box_id 
------------------------------------ 
1 |  2 | 12/19/2014 | null 
2 |  2 | 12/13/2014 | null 
3 |  2 | 08/11/2014 | null 
4 |  2 | 12/11/2014 | 99 
5 |  2 | null   | 99 
6 |  2 | 12/15/2014 | 99 
7 |  2 | null   | 105 
8 |  2 | null   | 105 
9 |  2 | null   | 105 

我已经是owner_id的唯一变量。 我需要选择一个用户的所有产品,但是如果产品在一个盒子里,那么应该只选择最新的一个。

样品输出所有者= 2以下:

id | owner_id | last_activity | box_id 
------------------------------------ 
1 |  2 | 12/19/2014 | null 
2 |  2 | 12/13/2014 | null 
3 |  2 | 08/11/2014 | null 
6 |  2 | 12/15/2014 | 99 
7 |  2 | null   | 105 

我不能找到一种方法来选择从盒子的最新产品。

我当前的查询,没有返回正确的值,但可以执行:

SELECT p.* FROM product p 
WHERE p.owner_id = 2 
AND (
    p.box IS NULL 
    OR (
    p.box IS NOT NULL 
    AND 
    p.id = (SELECT MAX(pp.id) FROM product pp 
      WHERE pp.box_id = p.box_id) 
) 

我试图用日期:

SELECT p.* FROM product p 
WHERE p.owner_id = 2 
AND (
    p.box IS NULL 
    OR (
    p.box IS NOT NULL 
    AND 
    p.id = (SELECT * FROM (
       SELECT pp.id FROM product pp 
       WHERE pp.box_id = p.box_id 
       ORDER BY last_activity desc 
      ) WHERE rownum = 1 
      ) 
) 

其中给出错误:p.box_id是未定义因为它在第二个子查询中。

你有什么想法,我该如何解决它?

+0

什么是_“最新”_?特别是,你在'last_activity'列中有'NULL'值 - 它们是如何考虑的。 – 2014-12-19 10:00:03

+0

是的,可以有空值作为值。如果盒子内的所有产品都有空白,则应返回MIN(id)。 – irytek102 2014-12-19 10:16:58

+0

这可能是**不是一个好主意,依靠'id'命令的东西。假设您从一个序列填充该列,请考虑并发访问:“id”的“池”可能已被客户端保留,但未立即使用... – 2014-12-19 10:21:05

回答

0

ROW_NUMBER分析功能可能有助于此类查询:

SELECT "owner_id", "id", "box_id", "last_activity" FROM 
(

    SELECT "owner_id", "id", "box_id", "last_activity", 
      ROW_NUMBER() 
      OVER (PARTITION BY "box_id" ORDER BY "last_activity" DESC NULLS LAST) rn 
      --             ^^^^^^^^^^^^^^^ 
      --    descending order, reject nulls after not null values 
      --         (this is the default, but making it 
      --         explicit here for self-documentation 
      --         purpose) 
    FROM T 
    WHERE "owner_id" = 2 

) V 
WHERE rn = 1 or "box_id" IS NULL 
ORDER BY "id" -- <-- probably not necessary, but matches your example 

请参阅http://sqlfiddle.com/#!4/db775/8


there can be nulls as a value. If there are nulls in all products inside a box, then MIN(id) should be returned

即使是可能依靠id订购的事情是,你认为你需要,你必须将ORDER BY条款更改为一个好主意:

... ORDER BY "last_activity" DESC NULLS LAST, "id" DESC 
--           ^^^^^^^^^^^ 
+0

是的! 'ROW_NUMBER'完成任务。谢谢!我想在这里我可以依靠id,因为我工作的系统按照给定的顺序插入产品,所以如果'last_activity'为null,我可以简单地使用'id'并且可以确定结果。 – irytek102 2014-12-19 10:39:52

0

使用存在

SELECT 
    p.* 
FROM 
    product p 
WHERE 
    p.owner_id = 2 AND 
    (p.box IS NULL OR 
    (
     p.box IS NOT NULL AND 
     NOT EXISTS 
     (
     SELECT 
      pp.id 
     FROM 
      product pp 
     WHERE 
      pp.box_id = p.box_id AND 
      pp.last_activity > p.last_activity 
    ) 
    ) 
) 
0

您可以使用工会首先要获得其中box_is空的所有行,比取,最大编号和日期行,其中box_id不为空:

SELECT * FROM 
(
    SELECT id,owner_id,last_activity,box_id FROM product WHERE owner_id = 2 AND box_id IS NULL 
    UNION 
    SELECT MAX(id),owner_id,MAX(last_activity),box_id FROM product WHERE owner_id = 2 AND box_id IS NOT NULL GROUP BY owner_id, box_id 
) T1 
ORDER BY 
    id