如果之前在组中没有看到值,则聚合值 - SQL / ORACLE

Posted

技术标签:

【中文标题】如果之前在组中没有看到值,则聚合值 - SQL / ORACLE【英文标题】:Aggregate values if value wasn't seen before in group - SQL / ORACLE 【发布时间】:2021-06-13 02:34:44 【问题描述】:

尝试在 Oracle 查询中执行此操作,但 SQL 也可以。我想知道是否有任何简单的功能或方法可以做到这一点,理论上我知道如何在 python 中做到这一点(参见下面的示例)

基本上我正在尝试运行一个总的不同计数,假设每月为一个唯一标识符让我们使用“customer_id”,但只有在前几个月没有看到它们时才将它们添加到总数中。

如果客户 1 在 1 月份出现,然后在 3 月份再次出现。它们只会出现在 1 月份的总数中并计为 1。 总计将是 unique_customers 的总数

....在 python 中,你会做一个 list ,检查客户是否在列表中,如果他们在,它什么都不做。如果不是,则将它们附加到列表中,然后添加到总和中。这只是唯一值的总和,它必须按月总计执行此操作,但理论上这是我想要的

l = []
total = 0
customers [12,123,1234,12345,123455]

for i in customers:
    if i in l:
        pass
    else:
        l.append(i)
        total += 1

return total

现在我正在输入这个并更多地考虑它,尽管我会做一个唯一客户及其最小(日期)销售的子查询。那么当

select count(distinct customer_id), month
from sales
group by month

不起作用,因为每个唯一客户都是按月计算的......但如果我这样做了

select count(customer_id), month
from 
(select customer_id, min(month)
from sales
group by customer_id)
group by month

这是否可行,因为它只使用客户的第一个销售月份作为总数?有没有更简单的方法来做到这一点,或者这样做是否有意义

【问题讨论】:

请注意,SQL 是一种语言。它受到一系列产品的支持 - 包括 Oracle 和 MS SQL Server...(“在 Oracle 查询中,但 SQL 也可以工作”) 您的表包含 customer_id 和月份,而 customer_id 不是键,对吗?而你想要的是一个表,其中包含 costomer_id 和月份,只有 customer_id 的第一个条目? 难道oracle没有自己的TSQL语法吗? TSQL 是 SQL Server 的过程语言,PL/SQL 是 oracle 的过程语言;它们都不是从另一个派生的,它们不是 SQL(但它们可以使用上下文切换在其中使用 SQL)。 SQL 语言是独立的,Oracle 和 SQL Server 都有自己的(略有不同)的 SQL 语法。 【参考方案1】:

您似乎想找到每个customer_id 的第一次出现;您可以为此使用分析函数,然后在第一次出现时进行过滤:

SELECT customer_id,
       month
FROM   (
  SELECT customer_id,
         month,
         ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY month ) AS rn
  FROM   sales
)
WHERE  rn = 1;

其中,对于样本数据:

CREATE TABLE sales ( customer_id, month ) AS
SELECT 1, DATE '2021-01-01' FROM DUAL UNION ALL
SELECT 1, DATE '2021-02-01' FROM DUAL UNION ALL
SELECT 1, DATE '2021-03-01' FROM DUAL UNION ALL
SELECT 1, DATE '2021-04-01' FROM DUAL UNION ALL
SELECT 1, DATE '2021-05-01' FROM DUAL UNION ALL
SELECT 2, DATE '2021-01-01' FROM DUAL UNION ALL
SELECT 3, DATE '2021-03-01' FROM DUAL UNION ALL
SELECT 3, DATE '2021-04-01' FROM DUAL UNION ALL
SELECT 3, DATE '2021-05-01' FROM DUAL UNION ALL
SELECT 4, DATE '2021-04-01' FROM DUAL UNION ALL
SELECT 4, DATE '2021-05-01' FROM DUAL;

输出:

客户 ID |月 ----------: | :-------- 1 | 01-JAN-21 2 | 01-JAN-21 3 | 01-MAR-21 4 | 01-APR-21

如果你想统计每个月之前没有见过的用户,那么只需将之前的查询和聚合:

SELECT COUNT(customer_id) AS number_of_new_customers,
       month
FROM   (
  SELECT customer_id,
         month,
         ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY month ) AS rn
  FROM   sales
)
WHERE  rn = 1
GROUP BY month
ORDER BY month;

对于相同的样本数据,输出:

NUMBER_OF_NEW_CUSTOMERS |月 ----------------------: | :-------- 2 | 01-JAN-21 1 | 01-MAR-21 1 | 01-APR-21

db小提琴here

【讨论】:

以上是关于如果之前在组中没有看到值,则聚合值 - SQL / ORACLE的主要内容,如果未能解决你的问题,请参考以下文章

在组中的所有单元格中放置小计值

如何在组中获得最小值?

聚合框架中的 rmongodb $cond

SQL Server:条件聚合;

SQL 聚合具有相同 id 的行,辅助列中的特定值

SQL Server 查找包含的组