获得MIN MAX分组距离更近

时间:2013-01-03 09:48:52

标签: sql postgresql

商店

id_shop | id_prod_ty | position

产品

id | price | id_prod_ty | distance

表商店为每个id_prod_ty(产品类型)和一个职位包含2个商店 表产品包含许多具有不同价格和距离的记录

基本上我需要有一个查询,为每个产品和每个商店分组选择价格较低和较高价格(并且不接近其他商店)

所以例如

商店

id_shop | id_prod_ty | position
  1     |     1      |    3
  2     |     1      |    7
  3     |     2      |    8
  4     |     2      |    4
....

产品

id | price | id_prod_ty | distance
1  |  10   |   1        |  1        
2  |  04   |   1        |  2 
3  |  02   |   1        |  4 
4  |  44   |   1        |  2 
5  |  09   |   1        |  1 
6  |  13   |   1        |  7
7  |  15   |   1        |  8
8  |  09   |   2        |  5 
9  |  12   |   2        |  8
10 |  17   |   2        |  1
11 |  32   |   2        | 13
12 |  22   |   2        |  2
...

结果大喊这样

id_prod_ty | id_price_low | id_price_high | id_shop
1          |     3 (02)   |      4 (44)   |  1
1          |     6 (13)   |      7 (15)   |  2
2          |     8 (09)   |     12 (22)   |  4
2          |     9 (12)   |     11 (32)   |  3
...

感谢

1 个答案:

答案 0 :(得分:0)

我想我明白了这个问题。对于每个价格,您尝试根据距离和位置分配最近的商店。

这种方法从加入职位和商店开始。然后计算位置和距离之间的差异 - 这似乎是您正在使用的度量。每个价格ID将出现两次(每个商店一次)。使用窗口函数,它计算每个id的最小差异。

通过此信息,查询可以确定哪个是最近的商店。此版本返回价格,而不是最低价格的ID。这是最终未经测试的查询:

select id_prod_ty,
       MIN(case when diff = minDiff then price) as price_low,
       MAX(case when diff = minDiff then price) as price_high,
       s.id_shop
from (select p.id_prod_ty,
             s.id_shop,
             p.price,
             (p.distance - s.position) as diff,
             MIN(p.distance - s.position) over (partition by p.id) as minDiff
      from products p join
           shops s
           on p.id_prod_ty = s.id_prod_ty
    ) ps
group by id_prod_ty, id_shop

这是一个获取ID的变体。它使用窗口函数来查找最小和最大价格,然后将价格与这些值进行比较以获得ID:

select id_prod_ty,
       MIN(minPrice) as price_low,
       MIN(case when price = minPrice then id end) id_price_low,
       MAX(maxprice) as price_high,
       MIN(case when price = maxPrice then id end) id_price_high,
       id_shop
from (select *,
             MIN(IsThisShopPrice) over (partition by id_prod_ty, id_shop) as minPrice,
             MIN(IsThisShopPrice) over (partition by id_prod_ty, id_shop) as maxPrice,
      from (select p.id_prod_ty, s.id_shop, p.price, p.id,
                   (p.distance - s.position) as diff,
                   (case when (p.distance - s.position) = MIN(p.distance - s.position) over (partition by p.id)
                         then 'Y'
                         else 'N'
                    end) as IsThisShop
                   (case when (p.distance - s.position) = MIN(p.distance - s.position) over (partition by p.id)
                         then price
                    end) as IsThisShopPrice
            from products p join
                 shops s
                 on p.id_prod_ty = s.id_prod_ty
           ) ps
    ) ps
group by id_prod_ty, id_shop