2011-12-31 42 views
2

这可能已经被问到,但StackOverflow是巨大的,并试图谷歌的具体事情足以实际帮助是一场噩梦!SQL - 加入两个结果表,重构想法?

我已经结束了一个相当大的SQL查询,并想知道是否可以指出更容易的方法来做到这一点,我可能错过了。

我有一个名为usage结构如下表:

host | character varying(32)  | 
usage | integer      | 
logtime | timestamp without time zone | default now() 

我想同时为MAX和MIN logtimes使用值。通过我的一些旧课本的工作(以来我真正使用SQL正确一段时间)之后,我结束了与此连接:

SELECT * 
FROM (SELECT u.host,u.usage AS min_val,r2.min 
    FROM usage u 
    JOIN (SELECT host,min(logtime) FROM usage GROUP BY host) r2 
    ON u.host = r2.host AND u.logtime = r2.min) min_table 
NATURAL JOIN (SELECT u.host,u.usage AS max_val,r1.max 
    FROM usage u 
    JOIN (SELECT host,max(logtime) FROM usage GROUP BY host) r1 
    ON u.host = r1.host AND u.logtime = r1.max) max_table 
; 

这似乎是一个混乱的方式做到这一点,因为我基本上运行相同的查询两次,一次使用MAX,一次使用MIN。通过执行SELECT usage,MAX(logtime),MIN(logtime) FROM ...,我可以在一个查询中获得两个日志时间列,但是我无法确定如何显示与这两个不同记录对应的使用情况值。

任何想法?

+0

哪个版本的PostgreSQL? – 2011-12-31 16:05:04

+0

PostgreSQL 9.1.2! 编辑:虽然这将最终连接到一个不受我管理的数据库,它运行的是8.4.9,如果这会造成很大的差异? – shearn89 2011-12-31 16:07:42

回答

3

在PostgreSQL 9.1你有窗口的功能在您的处置(8.4+):

SELECT DISTINCT 
     u.host 
     ,first_value(usage) OVER w AS first_usage 
     ,last_value(usage) OVER w AS last_usage 
FROM usage u 
WINDOW w AS (PARTITION BY host ORDER BY logtime, usage 
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 

我通过logtime排序的分区,并通过usage除了打破任何联系,并在一个稳定的结果到达。阅读关于window functions in the manual

有关更多解释和链接,您可能需要参考最近的相关答案herehere

+0

因此,WINDOW位基本上是做GROUP BY的,UNBOUNDED PRECEDING/FOLLOWING分别做最小/最大值? – shearn89 2011-12-31 16:11:50

+0

太棒了,这听起来就像我需要的!干杯! – shearn89 2011-12-31 16:15:09

+1

@ shearn89:'WINDOW'位仅仅是语法上的便利,所以你不必在上面两次解释'OVER'子句。聪明的部分是我使用DISTINCT在没有子查询的情况下一步到达结果的地方。 (最后应用DISTINCT。) – 2011-12-31 16:18:12