从组中排除列

时间:2015-06-30 12:23:51

标签: sql group-by min

我有一张表,「供应」,列出不同供应商的物品价格:

| ID | Item | Price | Supplier |

ID 是主键(只是一个自动生成的整数)。 Item 是产品的名称。 价格是产品的价格。 供应商是外键(整数)。

我想列出每件商品的最便宜的价格和供应商。

我对数据库比较陌生,到目前为止我已经有了这个:

SELECT Name, MIN(Price), Supplier FROM Supplies GROUP BY Name

这当然给了我错误

  

供应商不在聚合函数或group by子句中。

我已经做了一些谷歌搜索并阅读了很多关于这个主题的文章和答案,但它们似乎都比我的复杂情况要复杂得多(如上所述,我对数据库的经验不多) SQL)或者他们只是谈论错误而不是如何绕过它。

任何帮助将不胜感激。提前谢谢。

5 个答案:

答案 0 :(得分:1)

在大多数数据库中,您可以使用ANSI标准窗口函数:

select s.*
from (select s.*, min(price) over (partition by item) as minprice
      from supplies
     ) s
where price = minprice;

答案 1 :(得分:1)

根据您的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

请注意,如果所有供应商都以最低价格捆绑,则此查询将返回所有具有相同价格的供应商。

可以使用RANK()代替ROW_NUMBER()

强制执行第一个查询

答案 2 :(得分:0)

您可以对结果进行排名,然后选择最低/最高排名项(基于排序顺序)。假设您使用的是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

答案 3 :(得分:0)

问题的关键在于 - 如果您有多个供应商以完全相同(最低)的价格提供设备,该怎么办?那么应该在结果集中返回什么样的供应商?

实现您的目标的方法是获得最低价格,然后外部联接回到产品=产品和价格=等的同一个表格。但是要明白,如果您有上面的方案,您将返回两行 - 每个供应商提供最低价格。

自从我开始撰写本文以来,已经在这里出现了3到4个新答案,所以我愿意猜测实际的代码已经存在。我将此文本留在这里,简单的英语"解释为什么查询可以按照您期望的方式工作。

答案 4 :(得分:0)

如果您没有partition by(某些像Access这样的sql-ish环境),那么您也可以这样做:

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有效,因为它有一个子查询,每个名称的价格最低。请注意,如果出现平局,它将返回多个供应商;你可能会也可能不想那样。

相关问题