从分组依据中排除列
Exclude Column From Group By
我有一个 table,Supplies,它列出了来自不同供应商的商品的价格:
| ID | Item | Price | Supplier |
ID 是主键(只是一个自动生成的整数)。
Item是产品名称。 价格是产品的价格。 Supplier 是外键(整数)。
我想列出每件商品的最低价格和供应商。
我对数据库比较陌生,到目前为止我已经知道了:
SELECT Name, MIN(Price), Supplier FROM Supplies GROUP BY Name
这当然给了我
的错误
Supplier is not in an aggregate function or group by clause.
我做了一些 Google 搜索并阅读了很多关于这个主题的文章和答案,但它们似乎都比我的情况复杂得多,让我感到困惑(如前所述,我不有丰富的数据库经验和 SQL) 或者他们只是谈论错误而不是如何解决它。
如有任何帮助,我们将不胜感激。提前致谢。
在大多数数据库中,您可以使用 ANSI 标准 window 函数:
select s.*
from (select s.*, min(price) over (partition by item) as minprice
from supplies
) s
where price = minprice;
根据您的 RDBMS,您可以使用 ROW_NUMBER()
为每条记录分配排名并选择排名第一的记录。这比使用额外的连接或相关子查询更快,但例如,目前 MySQL 不支持。
WITH
sorted_supplies AS
(
SELECT
supplies.*,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY price) AS price_ordinal
FROM
supplies
)
SELECT
*
FROM
sorted_supplies
WHERE
price_ordinal = 1
;
如果没有对 ROW_NUMBER()
的支持,那么您几乎会被引导到其他聚合和连接的道路上...
SELECT
supplies.*
FROM
supplies
INNER JOIN
(
SELECT
name,
MIN(price) AS min_price
FROM
supplies
GROUP BY
name
)
AS min_prices
ON min_prices.name = supplies.name
AND min_prices.min_price = supplies.price
请注意,此查询将 return 所有供应商都以相同的价格提供相同的价格,如果他们都以最低价格并列的话。
可以使用 RANK()
而不是 ROW_NUMBER()
强制执行第一个查询
您可以对结果进行排名,稍后选择 lowest/highest 排名项目(基于排序顺序)。假设您使用的是 SQL Server 2008 或更高版本:
SELECT
Item, Price, Supplier
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Price ASC) PriceRank
, Item
, Price
, Supplier
FROM
Supplies
) supplies_ranked
WHERE
PriceRank = 1
问题的症结在于 - 如果您有不止一家供应商以完全相同(最低)的价格提供齿轮怎么办?那么应该在结果集中 return 编辑哪个供应商?
完成您所追求的方法是获取最低价格,然后在 product = product 和 price = price 等上外连接回到相同的 table。不过请理解,如果您遇到上述情况,您将 return 两行 - 每个供应商提供最低价格。
自从我开始撰写这篇文章以来,这里出现了 3 或 4 个新答案,所以我愿意猜测实际代码已经存在。我将在此处保留此文本,作为 "plain English" 对查询无法按您期望的方式工作的原因的解释。
如果您没有 partition by
(某些 sql-ish 环境,如 Access),那么您也可以这样做:
select s.name, s.supplier, s.price from
(select name, min(price) as min_price from supplies group by name) mp
join supplies s on mp.name=s.name and mp.min_price = s.price
这不如 partition by
有效,因为它有一个针对每个名称的最低价格的子查询。请注意,如果出现平局,它将 return 多个供应商;你可能想要也可能不想要那个。
我有一个 table,Supplies,它列出了来自不同供应商的商品的价格:
| ID | Item | Price | Supplier |
ID 是主键(只是一个自动生成的整数)。 Item是产品名称。 价格是产品的价格。 Supplier 是外键(整数)。
我想列出每件商品的最低价格和供应商。
我对数据库比较陌生,到目前为止我已经知道了:
SELECT Name, MIN(Price), Supplier FROM Supplies GROUP BY Name
这当然给了我
的错误Supplier is not in an aggregate function or group by clause.
我做了一些 Google 搜索并阅读了很多关于这个主题的文章和答案,但它们似乎都比我的情况复杂得多,让我感到困惑(如前所述,我不有丰富的数据库经验和 SQL) 或者他们只是谈论错误而不是如何解决它。
如有任何帮助,我们将不胜感激。提前致谢。
在大多数数据库中,您可以使用 ANSI 标准 window 函数:
select s.*
from (select s.*, min(price) over (partition by item) as minprice
from supplies
) s
where price = minprice;
根据您的 RDBMS,您可以使用 ROW_NUMBER()
为每条记录分配排名并选择排名第一的记录。这比使用额外的连接或相关子查询更快,但例如,目前 MySQL 不支持。
WITH
sorted_supplies AS
(
SELECT
supplies.*,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY price) AS price_ordinal
FROM
supplies
)
SELECT
*
FROM
sorted_supplies
WHERE
price_ordinal = 1
;
如果没有对 ROW_NUMBER()
的支持,那么您几乎会被引导到其他聚合和连接的道路上...
SELECT
supplies.*
FROM
supplies
INNER JOIN
(
SELECT
name,
MIN(price) AS min_price
FROM
supplies
GROUP BY
name
)
AS min_prices
ON min_prices.name = supplies.name
AND min_prices.min_price = supplies.price
请注意,此查询将 return 所有供应商都以相同的价格提供相同的价格,如果他们都以最低价格并列的话。
可以使用 RANK()
而不是 ROW_NUMBER()
您可以对结果进行排名,稍后选择 lowest/highest 排名项目(基于排序顺序)。假设您使用的是 SQL Server 2008 或更高版本:
SELECT
Item, Price, Supplier
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Price ASC) PriceRank
, Item
, Price
, Supplier
FROM
Supplies
) supplies_ranked
WHERE
PriceRank = 1
问题的症结在于 - 如果您有不止一家供应商以完全相同(最低)的价格提供齿轮怎么办?那么应该在结果集中 return 编辑哪个供应商?
完成您所追求的方法是获取最低价格,然后在 product = product 和 price = price 等上外连接回到相同的 table。不过请理解,如果您遇到上述情况,您将 return 两行 - 每个供应商提供最低价格。
自从我开始撰写这篇文章以来,这里出现了 3 或 4 个新答案,所以我愿意猜测实际代码已经存在。我将在此处保留此文本,作为 "plain English" 对查询无法按您期望的方式工作的原因的解释。
如果您没有 partition by
(某些 sql-ish 环境,如 Access),那么您也可以这样做:
select s.name, s.supplier, s.price from
(select name, min(price) as min_price from supplies group by name) mp
join supplies s on mp.name=s.name and mp.min_price = s.price
这不如 partition by
有效,因为它有一个针对每个名称的最低价格的子查询。请注意,如果出现平局,它将 return 多个供应商;你可能想要也可能不想要那个。