AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 320210
Accepted
gregoryp
gregoryp
Asked: 2022-11-26 13:13:10 +0800 CST2022-11-26 13:13:10 +0800 CST 2022-11-26 13:13:10 +0800 CST

MIN 函数在将列添加到 SELECT 后返回多行

  • 772

我正在尝试获取表中Price产品的最小值。DescriptionProductVariation

在此处输入图像描述

以这种方式创建我的查询时:

SELECT productId, MIN([price]) AS price
FROM ProductVariation
GROUP BY ProductId

它按预期工作,分组依据ProductId和最小值Price:

产品编号 价格
3个 299.99
6个 299.99
7 299.99
8个 199.99
9 299.99
10 299.99
11 159.99
12 159.99
13 189.99
14 189.99

但是,当我将Description列添加到SELECT:

SELECT productId, [Description], MIN([price]) AS price
FROM ProductVariation
GROUP BY ProductId, [Description]

它显示所有行,重复ProductId列。

产品编号 描述 价格
3个 自然 299.99
6个 饼干和奶油 299.99
7 莫兰戈 299.99
8个 包尼利亚 199.99
8个 巧克力 299.99
9 焦糖 299.99
10 包尼利亚 299.99
10 饼干和奶油 399.99
10 莫兰戈 399.99
11 包尼利亚 199.99
11 莫兰戈 159.99

我怎样才能修复它以显示独特的 ProductId价值以及它Description这样的东西?

产品编号 描述 价格
3个 自然 299.99
6个 饼干和奶油 299.99
7 莫兰戈 299.99
8个 包尼利亚 199.99
9 焦糖 299.99
10 包尼利亚 299.99
11 莫兰戈 159.99
12 包尼利亚 159.99
13 焦糖 189.99
14 莫兰戈 189.99

如果你能解释为什么它不按我的方式工作?

t-sql
  • 1 1 个回答
  • 92 Views

1 个回答

  • Voted
  1. Best Answer
    J.D.
    2022-11-26T13:25:49+08:002022-11-26T13:25:49+08:00

    您可以使用窗口函数ROW_NUMBER()来枚举 的分组(分区)中的行ProductId,按Price升序排序,然后SELECT只为每个组列出最小Price行。

    例如:

    WITH _ProductVariationsSorted AS
    (
        SELECT 
            ProductId, 
            Description,
            Price,
            ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY Price) AS SortId -- Generate a unique ID within each group of ProductId rows, sorted by the Price
        FROM dbo.ProductVariation
    )
    
    SELECT 
        ProductId, 
        Description,
        Price
    FROM _ProductVariationsSorted
    WHERE SortId = 1; -- Only return the rows with the lowest Price per ProductId grouping
    

    另一种方法(感谢 Erik Darling 提醒我)只是直接打开MIN()聚合函数的窗口。您还需要DISTINCT行。您可能会发现这简化了代码,如下所示:

    SELECT DISTINCT
        ProductId, 
        Description,
        MIN(Price) OVER (PARTITION BY ProductId) AS Price
    FROM dbo.ProductVariation
    

    最后,第三种但类似的方法也是使用FIRST_VALUE()窗口函数:

    SELECT DISTINCT
        ProductId, 
        Description,
        FIRST_VALUE(Price) OVER (PARTITION BY ID ORDER BY PRICE) AS Price
    FROM dbo.ProductVariation
    

    尽管取决于您的数据大小以及您的表和索引的架构方式,您可能会发现这些解决方案中的一个比另一个的性能更高。始终进行相应的测试。


    另一件需要注意的重要事情是,在使用窗口函数时,如果您正在窗口化的列中的值存在关联(在同一分组内),则不同的窗口函数将以不同方式处理这些关联。

    当按该绑定值排序时,该ROW_NUMBER()函数将非确定性地随机选择具有绑定的行之一来枚举行。然后,当对 进行过滤时,其中一个关系将被进一步过滤掉WHERE SortId = 1。DISTINCT使用或窗口函数SUM() OVER的解决方案FIRST_VALUE()将包括两个绑定的行。

    例如,在您的数据中,看起来ProductId = 10有两行具有相同的Price = 399.99,Cookies & Cream和Morango。现在这实际上不会在您的数据中造成问题,因为还有另一行ProductId = 10具有较低的Price.

    但是让我们假装有一天变体不再销售并且该行被删除。现在你的最低点Price是ProductId = 10两个399.99变体之间的平局。使用该ROW_NUMBER()解决方案,每次运行查询时,您只会随机返回其中一行。使用SUM() OVERorFIRST_VALUE()解决方案,您将返回两行。

    根据您的目标,这些结果可能都不是您想要的。也就是说,如果您真的只想一次只显示 1 个变体,即使在Pricesame中有联系ProductId,并且您希望每次运行查询时它都可靠地始终是相同的变体。

    为此,您必须ORDER BY在窗口函数的子句中添加一个确定性的决胜表达式ROW_NUMBER(),例如,一个唯一化的列,如Idcolumn。代码将如下所示ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY Price, Id) AS SortId:并且返回哪一行的规则现在是最低的那一行Price,并且在最低的平局中然后是平局中最低Price的行Id(理论上首先输入到ProductVariations表中)。

    • 4

相关问题

  • 如何使用 TSQL 更改 SQL 服务器配置管理器设置?

  • 如何从结果集中获取列名和类型的列表?

  • MS SQL:使用计算值计算其他值

  • 如何判断 SQL Server 数据库是否仍在使用?

  • 实施 PIVOT 查询

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve