如何使用MAX函数过滤INNER JOIN的结果

时间:2011-10-25 20:01:46

标签: sql postgresql inner-join

我需要在此查询的结果中添加一个带MAX函数的过滤器;

SELECT a.INTEGER_0, a.INTEGER_1, a.DATE_0, a.DATE_1, a.INTEGER_2
FROM TABLE_A a           
INNER JOIN               
   (SELECT b.INTEGER_0, b.INTEGER_1, b.DATE_0, max(b.DATE_1) AS max_date
    FROM TABLE_A b     
    GROUP BY b.INTEGER_0, b.INTEGER_1, b.DATE_0
   ) AS result         
ON  a.INTEGER_0 = b.INTEGER_0
AND a.INTEGER_1 = b.INTEGER_1
AND a.DATE_0 = b.DATE_0  
AND a.DATE_1 = b.max_date

这没关系!!但我需要过滤结果whit max(INTEGER_2) 我尝试了另一个INNER JOIN,但结果很糟糕!

其他信息
行:

1,7,'2011-02-01','2011-01-01',8
1,7,'2011-02-01','2011-01-02',7
1,7,'2011-02-01','2011-01-04',6
1,7,'2011-02-01','2011-01-04',3
1,7,'2011-02-01','2011-01-04',3

正确的结果:

1,7,'2011-02-01','2011-01-04',6

4 个答案:

答案 0 :(得分:1)

首先,您的查询中存在语法错误:子查询的别名为AS result。您将其与b的内部别名混淆。

1行

如果您只需要一个max(integer_2),那么ORDER BY / LIMIT就可以完成这项工作。您的查询可能如下所示:

SELECT a.integer_0, a.integer_1, a.date_0, a.date_1, a.integer_2
FROM   table_a a           
JOIN   (
    SELECT b.integer_0, b.integer_1, b.date_0, max(b.date_1) as max_date
    FROM   table_a b     
    GROUP  BY b.integer_0, b.integer_1, b.date_0
    ) AS b ON a.integer_0 = b.integer_0
        AND a.integer_1 = b.integer_1
        AND a.date_0 = b.date_0  
        AND a.date_1 = b.max_date
ORDER  BY a.integer_2 DESC
LIMIT  1;

所有行

如果您希望结果集的所有行包含max(integer_2)(正如您的查询所暗示的那样),那么您可以这样做:

SELECT a.integer_0, a.integer_1, a.date_0, a.date_1, a.integer_2
FROM   table_a a           
JOIN   (
    SELECT b.integer_0, b.integer_1, b.date_0, max(b.date_1) as max_date
    FROM   table_a b     
    GROUP  BY b.integer_0, b.integer_1, b.date_0
    ) AS b ON a.integer_0 = b.integer_0
        AND a.integer_1 = b.integer_1
        AND a.date_0 = b.date_0  
        AND a.date_1 = b.max_date
WHERE (a.date_1, a.integer_2) = (
        SELECT date_1, integer_2
        FROM   table_a
        ORDER  BY 1 DESC, 2 DESC
        LIMIT  1);

或者更好的是,大大简化为:

SELECT integer_0, integer_1, date_0, date_1, integer_2
FROM   table_a a           
WHERE     (integer_0, integer_1, date_0, date_1, integer_2) = ( 
    SELECT integer_0, integer_1, date_0, date_1, integer_2
    FROM   table_a b
    ORDER  BY 4 DESC, 5 DESC
    LIMIT  1);
-- ORDER  BY something?  -- add these lines ..
-- LIMIT  1;            -- .. if you want just one row 

或简化更多

SELECT *
FROM   table_a a           
WHERE  (a) = ( 
    SELECT b
    FROM   table_a b
    ORDER  BY date_1 DESC, integer_2 DESC
    LIMIT  1);
-- ORDER  BY something?  -- add these lines ..
-- LIMIT  1;            -- .. if you want just one row 

如果效果很重要,请确保在table_a(date_1,integer_2)上有索引。

答案 1 :(得分:0)

SELECT a.INTEGER_0, a.INTEGER_1, a.DATE_0, a.DATE_1, MAX(a.INTEGER_2) AS MaxInt2
FROM TABLE_A a           
INNER JOIN               
   (SELECT b.INTEGER_0, b.INTEGER_1, b.DATE_0, max(b.DATE_1) AS max_date
    FROM TABLE_A b     
    GROUP BY b.INTEGER_0, b.INTEGER_1, b.DATE_0
   ) AS result         
ON  a.INTEGER_0 = b.INTEGER_0
AND a.INTEGER_1 = b.INTEGER_1
AND a.DATE_0 = b.DATE_0  
AND a.DATE_1 = b.max_date
GROUP BY a.INTEGER_0, a.INTEGER_1, a.DATE_0, a.DATE_1
HAVING MAX(a.INTEGER_2) = 42 /* Adjust this according to what your filter needs */

答案 2 :(得分:0)

您尚未指定使用的PostgreSQL版本。如果它是8.4+,您可以尝试不同的方法并使用ranking function来实现目标:

WITH ranked AS (
  SELECT
    INTEGER_0,
    INTEGER_1,
    DATE_0,
    DATE_1,
    INTEGER_2,
    RANK() OVER (
      PARTITION BY
        INTEGER_0,
        INTEGER_1,
        DATE_0
      ORDER BY
        DATE_1 DESC
    ) AS rnk
  FROM TABLE_A
)
SELECT
  INTEGER_0,
  INTEGER_1,
  DATE_0,
  DATE_1,
  INTEGER_2
FROM TABLE_A
WHERE rnk = 1
ORDER BY INTEGER_2 DESC
LIMIT 1

答案 3 :(得分:0)

SET search_path='tmp';
-- generate some data
DROP TABLE atable CASCADE;
CREATE TABLE atable
    ( integer_0 INTEGER
    , integer_1 INTEGER
    , date_0 DATE
    , date_1 DATE
    , integer_2 INTEGER
    );  
INSERT INTO atable( integer_0,integer_1,date_0,date_1,integer_2)
VALUES
(1,7,'2011-02-01','2011-01-01',8)
,(1,7,'2011-02-01','2011-01-02',7)
,(1,7,'2011-02-01','2011-01-04',6)
,(1,7,'2011-02-01','2011-01-04',3)
,(1,7,'2011-02-01','2011-01-04',3)
    ;

-- Query the data
SELECT integer_0,integer_1,date_0,date_1,integer_2
FROM atable a0
WHERE NOT EXISTS (SELECT *
    FROM atable a1
    WHERE a1.integer_0 = a0.integer_0
    AND a1.integer_1 = a0.integer_1
    AND a1.date_0 = a0.date_0
    AND a1.date_1 > a0.date_1
    )   
AND NOT EXISTS (SELECT *
    FROM atable a2
    WHERE a2.integer_0 = a0.integer_0
    AND a2.integer_1 = a0.integer_1
    AND a2.date_0 = a0.date_0
    AND a2.date_1 = a0.date_1
    AND a2.integer_2 > a0.integer_2
    )   
    ;