MySQL - 查询:文章的最佳排名价格

MySQL - Query: Best ranked price for article

我有这个查询来查找可能的文章价格:

SELECT MAX(ranking), prices.* FROM (
    SELECT 
        case when merchant_id IS NOT NULL then 100 ELSE 0 END 
        + case when invoice_merchant_id IS NOT NULL then 90 ELSE 0 END 
        + case when merchant_group_id IS NOT NULL then 80 ELSE 0 END 
        + case when whitelist_id IS NOT NULL then 700 ELSE 0 END 
        + case when season_id IS NOT NULL then 60 ELSE 0 END 
        AS ranking,
        price.id, price.article_id
        FROM (
            select  6587 id, 1583 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  6618 id, 4561 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  6985 id, 1583 article_id, null merchant_id, NULL invoice_merchant_id, null whitelist_id, 1 merchant_group_id, 1 season_id union
            select  7015 id, 1583 article_id, 1 merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9119 id, 4561 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9931 id, 1583 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9965 id, 1583 article_id, null merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9988 id, 1583 article_id, null merchant_id, null invoice_merchant_id, 1 whitelist_id, null merchant_group_id, 1 season_id union
            select  10460 id, 4561 article_id, 1 merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id 
            )price
) AS prices
GROUP BY prices.id

结果是

| MAX(ranking)  | ranking   | id    | article_id|
| 150           | 150       | 6587  | 1583      |
| 150           | 150       | 6618  | 4561      |
| 140           | 140       | 6985  | 1583      |
| 160           | 160       | 7015  | 1583      |
| 150           | 150       | 9119  | 4561      |
| 150           | 150       | 9931  | 1583      |
| 60            | 60        | 9965  | 1583      |
| 760           | 760       | 9988  | 1583      |
| 160           | 160       | 10511 | 4561      |

现在我需要排名最高的每篇文章的两种价格:

| MAX(ranking)  | ranking   | id    | article_id|
| 760           | 760       | 9988  | 1583      |
| 160           | 160       | 10511 | 4561      |

我尝试过的,第 1 部分

SELECT MAX(ranking), prices.* FROM (
    SELECT 
        case when merchant_id IS NOT NULL then 100 ELSE 0 END 
        + case when invoice_merchant_id IS NOT NULL then 90 ELSE 0 END 
        + case when merchant_group_id IS NOT NULL then 80 ELSE 0 END 
        + case when whitelist_id IS NOT NULL then 700 ELSE 0 END 
        AS ranking,
        price.id, price.article_id
        FROM (
            #subquery query
        )price
) AS prices
GROUP BY prices.article_id

结果:

| MAX(ranking)  | ranking   | id    | article_id|
| 760           | 150       | 6587  | 1583      |
| 160           | 150       | 6618  | 4561      |

我尝试过的,第 2 部分

SELECT * FROM (
    SELECT MAX(ranking) max_ranking, prices.* FROM (
        SELECT 
            case when merchant_id IS NOT NULL then 100 ELSE 0 END 
            + case when invoice_merchant_id IS NOT NULL then 90 ELSE 0 END 
            + case when merchant_group_id IS NOT NULL then 80 ELSE 0 END 
            + case when whitelist_id IS NOT NULL then 700 ELSE 0 END 
            AS ranking,
            price.id, price.article_id
            FROM (
                #subquery query
            )price
    ) AS prices
    GROUP BY prices.id
) outer_prices
GROUP BY article_id
ORDER BY max_ranking desc

结果

| max_ranking   | ranking   | id    | article_id|
| 150           | 150       | 6587  | 1583      |
| 150           | 150       | 6618  | 4561      |

我尝试了一些来自 Whosebug 的更多解决方案,但没有任何效果。有人可以帮忙吗?

如果您使用的是 MYSQL 8 或更高版本,请尝试 ROW_NUMBER window 函数。

ROW_NUMBER

select * from(
SELECT row_number() over(partition by id    , article_id order by ranking desc) rn, prices.* FROM (
    SELECT 
        case when merchant_id IS NOT NULL then 100 ELSE 0 END 
        + case when invoice_merchant_id IS NOT NULL then 90 ELSE 0 END 
        + case when merchant_group_id IS NOT NULL then 80 ELSE 0 END 
        + case when whitelist_id IS NOT NULL then 700 ELSE 0 END 
        AS ranking,
        price.id, price.article_id
        FROM (
            #subquery query
        )price
) AS prices
) as main
where rn=1

低于MYSQL8 试试这个。

SELECT  RANKING,ID,ARTICLE_ID FROM (
    SELECT 
        case when merchant_id IS NOT NULL then 100 ELSE 0 END 
        + case when invoice_merchant_id IS NOT NULL then 90 ELSE 0 END 
        + case when merchant_group_id IS NOT NULL then 80 ELSE 0 END 
        + case when whitelist_id IS NOT NULL then 700 ELSE 0 END 
        + case when season_id IS NOT NULL then 60 ELSE 0 END 
        AS ranking,
        price.id, price.article_id
        FROM (
            select  6587 id, 1583 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  6618 id, 4561 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  6985 id, 1583 article_id, null merchant_id, NULL invoice_merchant_id, null whitelist_id, 1 merchant_group_id, 1 season_id union
            select  7015 id, 1583 article_id, 1 merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9119 id, 4561 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9931 id, 1583 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9965 id, 1583 article_id, null merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9988 id, 1583 article_id, null merchant_id, null invoice_merchant_id, 1 whitelist_id, null merchant_group_id, 1 season_id union
            select  10460 id, 4561 article_id, 1 merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id 
            )price
) AS prices
WHERE (ranking,article_id) IN (
(SELECT MAX(ranking),article_id FROM (
    SELECT 
        case when merchant_id IS NOT NULL then 100 ELSE 0 END 
        + case when invoice_merchant_id IS NOT NULL then 90 ELSE 0 END 
        + case when merchant_group_id IS NOT NULL then 80 ELSE 0 END 
        + case when whitelist_id IS NOT NULL then 700 ELSE 0 END 
        + case when season_id IS NOT NULL then 60 ELSE 0 END 
        AS ranking,
        price.id, price.article_id
        FROM (
            select  6587 id, 1583 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  6618 id, 4561 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  6985 id, 1583 article_id, null merchant_id, NULL invoice_merchant_id, null whitelist_id, 1 merchant_group_id, 1 season_id union
            select  7015 id, 1583 article_id, 1 merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9119 id, 4561 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9931 id, 1583 article_id, null merchant_id, 1 invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9965 id, 1583 article_id, null merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id union
            select  9988 id, 1583 article_id, null merchant_id, null invoice_merchant_id, 1 whitelist_id, null merchant_group_id, 1 season_id union
            select  10460 id, 4561 article_id, 1 merchant_id, null invoice_merchant_id, null whitelist_id, null merchant_group_id, 1 season_id 
            )price
) AS prices
GROUP BY article_id)
)