【问题标题】:sql select earliest date for multiple rowssql选择多行的最早日期
【发布时间】:2012-11-06 03:54:09
【问题描述】:

我有一个如下所示的数据库;

circuit_uid   |  customer_name   | location      | reading_date | reading_time | amps | volts  |  kw  | kwh | kva  |  pf  |  key
--------------------------------------------------------------------------------------------------------------------------------------
cu1.cb1.r1    | Customer 1       | 12.01.a1      | 2012-01-02   | 00:01:01     | 4.51 | 229.32 | 1.03 |  87 | 1.03 | 0.85 |    15
cu1.cb1.r1    | Customer 1       | 12.01.a1      | 2012-01-02   | 01:01:01     | 4.18 | 230.3 | 0.96 |  90 | 0.96 | 0.84 |    16
cu1.cb1.s2    | Customer 2       | 10.01.a1      | 2012-01-02   | 00:01:01     | 7.34 | 228.14 | 1.67 | 179 | 1.67 | 0.88 | 24009
cu1.cb1.s2    | Customer 2       | 10.01.a1      | 2012-01-02   | 01:01:01     | 9.07 |  228.4 | 2.07 | 182 | 2.07 | 0.85 | 24010
cu1.cb1.r1    | Customer 3       | 01.01.a1      | 2012-01-02   | 00:01:01     | 7.32 | 229.01 | 1.68 | 223 | 1.68 | 0.89 | 48003 
cu1.cb1.r1    | Customer 3       | 01.01.a1      | 2012-01-02   | 01:01:01     | 6.61 | 228.29 | 1.51 | 226 | 1.51 | 0.88 | 48004

我要做的是生成一个结果,该结果在该日期最早 (min(reading_time)) 为每个客户读取 KWH,该日期将由用户在网络表单中选择。

结果将/应该类似于;

Customer 1   87
Customer 2   179
Customer 3   223

这里显示的每天的行数超过了,客户也更多,客户的数量会定期变化。

我对 SQL 没有太多经验,我看过子查询等,但我没有能力通过每个客户的最早阅读来确定如何安排它,然后只输出 kwh 列。

这是在 Redhat/CentOS 上的 PostgreSQL 8.4 中运行的。

【问题讨论】:

  • 请提出一个新问题。在给出好的答案之后,通常不能大幅改变问题的性质。您始终可以链接回此内容以获取上下文。我恢复了您的更改,您可以在编辑日志中找到它。

标签: sql postgresql greatest-n-per-group


【解决方案1】:
select customer_name,
       kwh,
       reading_date, 
       reading_time
from (
   select customer_name,
          kwh,
          reading_time,
          reading_date,
          row_number() over (partition by customer_name order by reading_time) as rn
   from readings
   where reading_date = date '2012-11-17'
) t
where rn = 1

作为替代方案:

select r1.customer_name,
       r1.kwh, 
       r1.reading_date,
       r1.reading_time
from readings r1
where reading_date = date '2012-11-17'
and reading_time = (select min(r2.reading_time)
                    from readings
                    where r2.customer_name = r1.customer_name
                    and r2.read_date = r1.reading_date);

但我希望第一个更快。

顺便说一句:为什么将日期和时间存储在两个单独的列中?您是否知道使用timestamp 列可以更好地处理此问题?

【讨论】:

  • 关于时间戳列的要点。提取日期或时间超级简单且超级快速:ts_column::datets_column::time
  • 我想只是我缺乏经验让我把日期和时间分开了。感谢您的出色回答。请接受我的道歉并查看修改后的问题。
【解决方案2】:

这应该是最快的解决方案之一:

SELECT DISTINCT ON (customer_name)
       customer_name, kwh  -- add more columns as needed.
FROM   readings
WHERE  reading_date = user_date
ORDER  BY customer_name, reading_time

似乎是另一个应用:

【讨论】:

  • 欧文谢谢你的回答我很抱歉改变这样的问题。您的回答也会为每个问题返回一个完美的结果。
  • @AlanEnnis:没问题。只需提出一个新问题,您将立即获得更多答案。 :)
【解决方案3】:
   SELECT rt.circuit_uid ,  rt.customer_name, rt.kwh
   FROM READING_TABLE rt JOIN  
       (SELECT circuit_uid, reading_time
       FROM READING_TABLE
       WHERE reading_date = '2012-01-02'
       GROUP BY customer_uid
       HAVING MIN(reading_time) = reading_time) min_time
   ON (rt.circuit_uid = min_time.circuit_uid 
      AND rt.reading_time = min_time.reading_time);

参数化上述查询中的 reading_date 值。

【讨论】:

  • 这会给你一个错误,因为kwh 既不在group by 子句中也不在聚合中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 1970-01-01
  • 2020-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多