【问题标题】:SQL Find a minimum number for each value in analytical functionSQL 查找分析函数中每个值的最小值
【发布时间】:2018-09-18 17:21:55
【问题描述】:

我正在使用 Microsoft SQL Server。我想写一个只有分析功能的查询(比如不使用 group by)

我想编写一个返回以下行的查询:

  • MIN(Customer_number), count(code), private
  • MIN(客户编号)、计数(代码)、业务

例如,我做了两张表

在这个例子中,它应该只适用于 Customer_number = 1,2 的行,如下所示:

* 1,intermediate results counting,private
.
.
.
* 2, intermediate results counting, business
.
.
.

我写道:

SELECT 
    MIN(subscribers.customer_number) OVER (PARTITION BY customers.customer_number, customer_type) AS cusNo,
    COUNT(subscribers.code) OVER (PARTITION BY customers.customer_number, customer_type) AS subscribes,
    customer_type
FROM
    customers 
JOIN
    subscribers ON subscribers.customer_number = customers.customer_number;

我尝试了这么多时间来了解如何返回正确的输出,为什么它不起作用并且找不到它

如果有人可以帮助我了解如何订购并解释问题所在,那就太好了。

【问题讨论】:

  • 编辑您的问题并提供您尝试生成的结果集。

标签: sql sql-server function analytical


【解决方案1】:

您似乎只需要客户 1 和 2,我将其解释为您只需要编号最低的私人客户和最低编号的企业客户。

您不想使用分组依据。

SELECT * FROM
  (
    SELECT
      --number each row, order by customer number, "group" by business type 
      ROW_NUMBER() OVER(PARTITION BY c.customer_type ORDER BY c.customer_number) rown, 
      --it isn't totally clear if you want the count of codes per customer or per type
      count(s.code) OVER (partition by c.customer_number) AS count_codes_by_cust,
      count(s.code) OVER (partition by c.customer_type) AS count_codes_by_type,
      customer_type 
    FROM
      customers c 
      INNER JOIN
      subscribers s
      ON s.customer_number = c.customer_number
  ) c
WHERE rown = 1 --cust #1 and cust#2 both have a rown of 1

请注意,为了清楚起见,我已将连接留给订阅者并从中计算代码 - 您最初尝试遗漏的关键概念是使用 WHERE 将输出限制为仅两行

您的第一次尝试也可以修改为产生需求:

SELECT * FROM
(
 SELECT 
  min(c.customer_number) OVER (partition by c.customer_type) AS min_cust,
  c.customer_number,
  --it isn't totally clear if you want the count of codes per customer or per type
  count(s.code) OVER (Partition by c.customer_number) AS count_codes_by_cust,
  count(s.code) OVER (Partition by c.customer_type) AS count_codes_by_type,
  customer_type
 FROM 
  customers c 
  INNER JOIN
  subscribers s
  ON s.customer_number = c.customer_number
)d
WHERE
  min_cust = customer_number

但是这种方法的一个缺陷是它给出了多行,因为加入客户和订阅者会导致客户编号重复,并且您最终会得到不止一行 where min_cust = customer number 为真:min(customer_number) over (...) 已选择“1”和“2”作为您的最小客户数量,但由于加入订阅者,1 出现 3 次,2 出现两次

row_number 方法在这方面有所不同 = 每个 customer_type 只有一行的行号可以为 1,因此您只能获得与不同类型的客户一样多的行。更笼统地说,如果您有一个表格,例如存储文档的多个日期版本,并且您只需要每个文档的最新版本,您可以:

SELECT * FROM (
  SELECT 
    doc.*, 
    ROW_NUMBER() OVER(PARTITION BY filename ORDER BY filedate DESC) --latest is numbered 1
  FROM
    documents
)doc WHERE rown = 1

要更详细地查看操作,请仅突出显示并运行内部查询,以查看外部查询正在操作的原始数据。

【讨论】:

  • SQL Server 不同意您的观点 - “窗口函数只能出现在 SELECT 或 ORDER BY 子句中。” :)
  • 非常感谢,我采用了第二种解决方案并更改了代码,因此它会计算“代码”列并且它可以工作。但是我不理解您的第一个解决方案,使用 row_number,它如何适合一般问题,而不是像这个示例,当您知道每个表中只有 4 行并且知道要检查哪些行时。或者也许我错过了它的概念。谢谢:)
  • @John 您在每个客户类型的最小客户数量之后:如果您按 customer_number 升序对行进行编号,并在 customer_type 更改时重新编号,那么您的两个最小客户编号将有行数字 1。作为一种通用技术,我经常使用它,因为我经常想要一堆值中的“第一个”。在某些情况下,它与第二种解决方案略有不同,例如如果两个客户编号相同,则说 where cust_num = min_cust 将返回两者,因为两个客户共享一个最小值,但 row_number = 1 只给出 1 行
  • 我已经编辑了答案以调整其中的代码,意识到如果您想要(仅)两行,那么第二种方法可能存在缺陷,因为它可能会产生超过 2 行
猜你喜欢
  • 1970-01-01
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
相关资源
最近更新 更多