我正在尝试获取表中Price
产品的最小值。Description
ProductVariation
以这种方式创建我的查询时:
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 |
如果你能解释为什么它不按我的方式工作?
您可以使用窗口函数
ROW_NUMBER()
来枚举 的分组(分区)中的行ProductId
,按Price
升序排序,然后SELECT
只为每个组列出最小Price
行。例如:
另一种方法(感谢 Erik Darling 提醒我)只是直接打开
MIN()
聚合函数的窗口。您还需要DISTINCT
行。您可能会发现这简化了代码,如下所示:最后,第三种但类似的方法也是使用
FIRST_VALUE()
窗口函数:尽管取决于您的数据大小以及您的表和索引的架构方式,您可能会发现这些解决方案中的一个比另一个的性能更高。始终进行相应的测试。
另一件需要注意的重要事情是,在使用窗口函数时,如果您正在窗口化的列中的值存在关联(在同一分组内),则不同的窗口函数将以不同方式处理这些关联。
当按该绑定值排序时,该
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() OVER
orFIRST_VALUE()
解决方案,您将返回两行。根据您的目标,这些结果可能都不是您想要的。也就是说,如果您真的只想一次只显示 1 个变体,即使在
Price
same中有联系ProductId
,并且您希望每次运行查询时它都可靠地始终是相同的变体。为此,您必须
ORDER BY
在窗口函数的子句中添加一个确定性的决胜表达式ROW_NUMBER()
,例如,一个唯一化的列,如Id
column。代码将如下所示ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY Price, Id) AS SortId
:并且返回哪一行的规则现在是最低的那一行Price
,并且在最低的平局中然后是平局中最低Price
的行Id
(理论上首先输入到ProductVariations
表中)。