Выберите пары значений на основе условия в другом столбце - PostgreSQL - PullRequest
0 голосов
/ 28 марта 2020

Последние пару дней я пытался решить проблему, но не мог понять, каким будет решение ...

У меня есть следующая таблица:

+--------+-----------+-------+
| ShopID | ArticleID | Price |  
+--------+-----------+-------+
|      1 |         3 |   150 | 
|      1 |         2 |    80 |  
|      3 |         3 |   100 |  
|      4 |         2 |    95 |  
+--------+-----------+-------+

И я бы хотел выбрать пары идентификаторов магазинов, для которых цена того же товара выше. Например, это должно выглядеть так:

+----------+----------+---------+
| ShopID_1 | ShopID_2 |ArticleID|
+----------+----------+---------+
|        4 |        1 |       2 |
|        1 |        3 |       3 |
+----------+----------+---------+

... показывая, что статья 2 в ShopID 4 дороже, чем в ShopID 2. Et c

Мой код выглядит следующим образом :

SELECT ShopID AS ShopID_1, ShopID AS ShopID_2, ArticleID FROM table
WHERE table.ArticleID=table.ArticleID and table.Price > table.Price

Но это не дает результата, который я ищу.

Может кто-нибудь помочь мне с этой целью? Большое спасибо.

Ответы [ 2 ]

2 голосов
/ 28 марта 2020

Проблема здесь заключается в вычислении элементов Top N на группу.

Предполагается, что у вас есть следующие данные в таблице sales.

# select * from sales;
 shopid | articleid | price 
--------+-----------+-------
      1 |         2 |    80
      3 |         3 |   100
      4 |         2 |    95
      1 |         3 |   150
      5 |         3 |    50

С помощью следующего запроса мы можем создать раздел для каждого ArticleId

select 
  ArticleID, 
  ShopID, 
  Price, 
  row_number() over (partition by ArticleID order by Price desc) as Price_Rank from sales;

Это приведет к:

 articleid | shopid | price | price_rank 
-----------+--------+-------+------------
         2 |      4 |    95 |          1
         2 |      1 |    80 |          2
         3 |      1 |   150 |          1
         3 |      3 |   100 |          2
         3 |      5 |    50 |          3

Затем мы просто выберем 2 лучших элемента для каждого AritcleId:

select 
  ArticleID,  
  ShopID, 
  Price
from (
  select 
    ArticleID, 
    ShopID, 
    Price, 
    row_number() over (partition by ArticleID order by Price desc) as Price_Rank 
  from sales) sales_rank
where Price_Rank <= 2;

, который В результате:

 articleid | shopid | price 
-----------+--------+-------
         2 |      4 |    95
         2 |      1 |    80
         3 |      1 |   150
         3 |      3 |   100

Наконец, мы можем использовать функцию crosstab, чтобы получить ожидаемый сводный вид.

select * 
from crosstab(
  'select 
    ArticleID,  
    ShopID, 
    ShopID
  from (
    select 
      ArticleID, 
      ShopID, 
      Price, 
      row_number() over (partition by ArticleID order by Price desc) as Price_Rank 
    from sales) sales_rank
  where Price_Rank <= 2')
AS sales_top_2("ArticleID" INT, "ShopID_1" INT, "ShopID_2" INT);

И результат:

 ArticleID | ShopID_1 | ShopID_2 
-----------+----------+----------
         2 |        4 |        1
         3 |        1 |        3

Примечание: вам может потребоваться позвонить CREATE EXTENSION tablefunc; в случае, если вы получите ошибку function crosstab(unknown) does not exist.

0 голосов
/ 28 марта 2020

Этот запрос должен работать:

SELECT t1.ShopID AS ShopID_1, t2.ShopID AS ShopID_2, t1.ArticleID
FROM <yourtable> t1 JOIN
     <yourtable> t2
     ON t1.ArticleID = t2.ArticleID AND t1.Price > t2.Price;

То есть вам требуется самостоятельное объединение и соответствующие псевдонимы таблиц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...