具有具有最小值、最大值的 SQL 语句

Posted

技术标签:

【中文标题】具有具有最小值、最大值的 SQL 语句【英文标题】:SQL statement with having, min , max 【发布时间】:2020-01-27 22:21:03 【问题描述】:

我有一张桌子:

 ID                INTEGER NOT NULL,  -- AUTOMATIC RECORD'S ID
 CUSTOMER_ID       INTEGER NOT NULL,
 BILING_PERIOD     DATE    NOT NULL,
 DOCUMENT_ID       INTEGER NOT NULL,   
 DATE_CREATED      DATE    NOT NULL  -- WHEN THE DOCUMENT WAS CREATED

我想在计费期间为客户选择文件数量, 为客户在计费期间首先创建的文档的 ID 以及在客户计费期间最后创建的文档的 ID。 所有都应按客户和计费周期分类。 我只需要为客户提供超过 1 个文档的计费周期。

所以当我们有例如这样的数据时:

ID CUSTOMER_ID BILING_PERIOD DOCUMENT_ID DATE_CREATED
1  5           2020-01-01    123         2020-02-01
2  5           2020-01-01    22          2019-02-01
3  5           2020-01-01    3           2010-02-01
4  99          2020-01-01    458         2021-02-01
5  99          2020-01-01    64          2010-02-01
6  100         2020-01-01    120         2020-02-01
7  99          2019-06-01    452         2019-06-01
8  99          2019-06-01    546         2019-12-01

我希望我的结果看起来像这样:

CUSTOMER_ID BILING_PERIOD NR_OF_DOC FIRST_DOC_ID LAST_DOC_ID
5           2020-01-01    3         3            123
99          2019-06-01    2         452          546
99          2020-01-01    2         64           458

我自己只能计算每个用户和期间的文档数

SELECT customer_id, biling_period, count(*) as nr_of_doc
FROM T1
GROUP BY customer_id, biling_period
HAVING COUNT() > 1;

CUSTOMER_ID BILING_PERIOD NR_OF_DOC 
5           2020-01-01    3         
99          2019-06-01    2         
99          2020-01-01    2 

我不知道如何获取最新和最旧文档的 document_id。

【问题讨论】:

用您正在使用的数据库标记您的问题。 【参考方案1】:

您可以使用row_number() 和聚合:

select 
    customer_id,
    billing_period,
    count(*),
    max(case when rn_asc  = 1 then document_id end) fist_doc_id,
    max(case when rn_desc = 1 then document_id end) last_doc_id
from (
    select 
        t.*,
        row_number() over( 
            partition by customer_id, billing_period order by date_created
        ) rn_asc,
        row_number() over( 
            partition by customer_id, billing_period order by date_created desc
        ) rn_desc
    from t1 t
) t
group by customer_id, billing_period
having count(*) > 1
order by customer_id, billing_period

即使文档 ID 不按顺序,这也会正常工作。

Demo on DB Fiddle

客户 ID |计费周期 |计数 |拳头文档ID | last_doc_id ----------: | :------------- | ----: | ----------: | ----------: 5 | 2020-01-01 | 3 | 3 | 123 99 | 2019-06-01 | 2 |第452章546 99 | 2020-01-01 | 2 | 64 | 458

【讨论】:

很好的解决方案,考虑到customer_id 字段可能有间隙。我自己做了一百次这样的事情,但这个答案似乎是我迄今为止看到的最干净的答案。【参考方案2】:

在您的示例数据中,文档 ID 似乎是按顺序分配的。如果是这种情况,您可以只使用聚合:

SELECT customer_id, billing_period, count(*) as nr_of_doc,
       MIN(document_id), MAX(document_id)
FROM T1
GROUP BY customer_id, billing_period
HAVING COUNT() > 1;

【讨论】:

不幸的是,事实并非如此

以上是关于具有具有最小值、最大值的 SQL 语句的主要内容,如果未能解决你的问题,请参考以下文章

如何缩小具有已知最小值和最大值的数字范围

SQL选择具有最大和最小日期的行

从具有多列的 .txt 文件中查找最大值、最小值

Pyspark - 从具有最小值和最大值范围的数组中获取值

从数据框中提取具有最小值或最大值的行

在 Pandas、Python 中查找具有相同第一列的所有行的最小值、最大值、平均值