如何获得每个公司的每种产品类型的最便宜的产品?

时间:2018-11-29 13:00:27

标签: sql sql-server

我以前使用以下方式列出了有效优惠:

SELECT
    pt.prod_type_description 'Tipo do Produto',
    p.prod_brand 'Marca',
    c.comp_fantasy_name 'Nome da Empresa',
    o.offer_price 'Preco'
FROM offer                  AS o
    INNER JOIN company      AS c ON o.comp_id = c.comp_id
    INNER JOIN product      AS p ON o.prod_id = p.prod_id
    INNER JOIN product_type AS pt ON p.prod_type_id = pt.prod_type_id
WHERE 
    CONVERT(VARCHAR, o.offer_expired_at, 23) >= CONVERT(VARCHAR, dbo.datetimeBrasilia(), 23)
GROUP BY pt.prod_type_id, o.offer_price, p.prod_id, c.comp_fantasy_name, pt.prod_type_description, p.prod_brand, o.offer_id

但是我的问题是如何获得每个公司每种产品中最便宜的产品(不受品牌的重视)?

TYPE PRODUCT    |     BRAND     |   COMPANY     |   PRICE
----------------------------------------------------------
Cimento	            Cauê	    MAConstuc	    13.65
Areia	            AB Areias	    MAConstuc	    15.79
Brita	            Briforte	    MAConstuc	    21.30
Paver PaviS	    MotriX	    MAConstuc	    0.65
Paver Raquete	    Forten	    TilJola	    1.20
Cimento	            Votoran	    TilJola	    10.40
Cimento	            Cauê	    TilJola	    14.65
Areia	            AB Areias	    TilJola	    11.56
Brita	            Briforte	    TilJola	     9.99
Paver PaviS	    MotriX	    TilJola	     1.30
Paver Raquete	    Forten	    TilJola	     1.00
Cimento	            Votoran	    KiCalc	    22.90
Cimento	            Cauê	    KiCalc	    20.00
Areia	            AB Areias	    KiCalc	    18.30
Brita	            Briforte	    KiCalc	    17.00
Paver PaviS	    MotriX	    KiCalc	     1.35
Paver Raquete	    Forten	    KiCalc	     0.99

-- example of company TilJola (without Cimento Cauê)
Cimento	            Votoran	        TilJola	        10.40
Areia	            AB Areias	        TilJola	        11.56
Paver PaviS	    MotriX	        TilJola	        1.30
Paver Raquete	    Forten	        TilJola	        1.00

-- example of company KiCalc (without Cimento Votoran)
Cimento	            Cauê	        KiCalc	        20.00
Areia	            AB Areias	        KiCalc	        18.30
Brita	            Briforte	        KiCalc	        17.00
Paver PaviS	    MotriX	        KiCalc	        1.35
Paver Raquete	    Forten	        KiCalc	        0.99

以前,我使用以下方式列出了有效优惠:

2 个答案:

答案 0 :(得分:3)

鉴于查询的这种结构,最简单的方法是order by中带有top (1) with ties的窗口函数:

SELECT TOP (1) WITH TIES
       pt.prod_type_description as [Tipo do Produto],
       p.prod_brand as Marca,
       c.comp_fantasy_name as [Nome da Empresa],
       o.offer_price as Preco
FROM offer        o JOIN
     company      c
     ON o.comp_id = c.comp_id JOIN
     product      p
     ON o.prod_id = p.prod_id JOIN
     product_type pt
     ON p.prod_type_id = pt.prod_type_id
WHERE offer_expired_at >= dbo.datetimeBrasilia()
GROUP BY pt.prod_type_id, o.offer_price, p.prod_id, c.comp_fantasy_name, pt.prod_type_description, p.prod_brand, o.offer_id
ORDER BY ROW_NUMBER() OVER (PARTITION BY pt.prod_type_description, pt.comp_fantasy_name ORDER BY o.offer_price);

请注意查询的其他更改:

  • 日期应作为日期而不是字符串进行比较。
  • 在SQL Server中,切勿使用没有长度的VARCHAR。长度因上下文而异,由于长度不够而导致的修复问题真的很难调试。
  • 仅对字符串和日期常量使用单引号。如果您开始将它们用作列名,那么最终会出错。
  • 我仅将as用于列别名,而从未将其用于表别名。诚然,这只是一个首选项,但我认为它可以最大程度地减少出错的机会(尤其是在select中加入逗号。

答案 1 :(得分:1)

您可以尝试使用row_number()函数

select * from 
(
SELECT
    pt.prod_type_description 'Tipo do Produto',
    p.prod_brand 'Marca',
    c.comp_fantasy_name 'Nome da Empresa',
    o.offer_price 'Preco',
 row_number() over(partition by c.comp_fantasy_name,pt.prod_type_description order by o.offer_price) as rn
FROM offer                  AS o
    INNER JOIN company      AS c ON o.comp_id = c.comp_id
    INNER JOIN product      AS p ON o.prod_id = p.prod_id
    INNER JOIN product_type AS pt ON p.prod_type_id = pt.prod_type_id
WHERE 
    CONVERT(VARCHAR, o.offer_expired_at, 23) >= CONVERT(VARCHAR, dbo.datetimeBrasilia(), 23)
)A where rn=1