【问题标题】:Sort records with field that don't exist使用不存在的字段对记录进行排序
【发布时间】:2020-07-14 21:34:09
【问题描述】:

我有一个有 4 列的表格:

| id | article_id | meta_key | meta_value |
|----|------------|----------|------------|
| 1  | 135        | author   | Beth       |
| 2  | 135        | status   | draft      |
| 3  | 135        | paywall  | yes        |
| 4  | 136        | author   | Kim        |
| 5  | 136        | status   | publish    |
| 6  | 137        | author   | Mary       |
| 7  | 137        | status   | publish    |

我必须实现一个功能,将带有 yesno meta_valuemeta_key“付费墙”添加到新文章中,这意味着 meta_key旧记录不存在“付费墙”。

我需要通过 meta_key="paywall" 获取记录并按 meta_value 排序。 问题在于没有meta_key“paywall”的文章,当排序为DESC时,文章按[是],[否],[没有付费墙元键的文章]排序。

SQL 中有没有一种方法,我可以通过假设 meta_value 的值为 yes 对于不存在的键进行排序,以便 DESC 返回为 [ Yes ],[ 没有文章付费墙元键],[否]?

我的查询:

SELECT article_id, meta_key, meta_value
FROM wp_meta
WHERE meta_key="paywall"
ORDER BY meta_value
DESC

【问题讨论】:

  • 您能分享您的查询吗?
  • @Mureinik 添加了查询
  • 如果你“需要通过 meta_key = 'paywall' 获取文章” 即 WHERE meta_key = 'paywall',你为什么要关心没有这个 meta_key 的旧文章?它们不属于您的结果集!
  • 我们需要假设旧文章有付费墙,值为“是”

标签: mysql sql


【解决方案1】:

如果我理解正确:

select article_id
from t
group by article_id
order by sum(meta_key = 'paywall' and value = 'yes') desc,
         sum(meta_key = 'paywall') = 0 desc;

这将“是”放在首位。然后是缺失值。然后是其余的(大概是“否”)。

【讨论】:

    【解决方案2】:

    您可以使用的一个肮脏技巧是按文章 ID 分组,并使用 max 运算符从采用 paywall 值的 case 表达式中获取元值,然后硬编码 no对于任何其他键,以模拟为没有此条目的文章获取no

    SELECT   article_id, 
             'paywall' AS meta_key,
             MAX(CASE meta_key WHEN 'paywall' THEN meta_value ELSE 'no' END) AS meta_value
    FROM     wp_meta
    GROUP BY article_id
    ORDER BY 3 DESC
    

    【讨论】:

      【解决方案3】:

      我们需要假设旧文章有付费墙,值为“是”

      只需为所有旧文章插入“是”作为一次性操作:

      INSERT INTO wp_meta (article_id, meta_key, meta_value)
      
      SELECT all_ids.article_id, 'paywall', 'yes'
      FROM
        (SELECT DISTINCT article_id FROM wp_meta) all_ids
        LEFT JOIN
        (SELECT article_id FROM wp_meta WHERE meta_key = 'paywall') paywall_ids
        ON all_ids.article_id = paywall_ids.article_id
      WHERE paywall_ids.article_id IS NULL
      

      您可以在没有插入的情况下运行选择,以检查它是否按预期工作。它是如何工作的:

      • 获取所有文章 ID 的列表
      • 获取仅包含付费专区的文章列表
      • left join the paywall to all,这意味着所有在 all_ids 中没有匹配到 paywall_ids 的文章 ID 将在 paywall_ids.article_id 列中生成 NULL
      • 检查这个空值
      • 创建一个要插入的行,将付费专区指定为 yes

      另一种方法,仅在您确定 article_ids 正在递增并且所有没有付费专区条目的文章 id 都出现在特定 id 之前时使用:

      INSERT INTO wp_meta (article_id, meta_key, meta_value)
      
      SELECT DISTINCT article_id, 'paywall', 'yes'
      FROM
        wp_meta
      WHERE 
        article_id < (SELECT MIN(article_id) FROM wp_meta WHERE meta_key = 'paywall')
      
      • 找到第一个使用付费专区的 ID
      • 选择该条目之前的所有唯一文章 ID 并创建一个付费专区条目
      • 插入它们

      左加入路线更安全,因为它会找到任何没有付费专区的文章,而不仅仅是某个 ID 之前的所有文章。我之所以建议这样做,是因为您表示您在某个时候将其打开,因此很可能之前的所有人都没有它,而之后的所有人都拥有它

      修复你的数据总是比运行破解虚假数据的 SQL 更可取——这意味着你可以将一些旧文章转为付费墙——如果你愿意,不可以


      顺便说一句,如果您还没有完成付费专区功能,最简单的方法是在启用该功能之前为所有文章插入付费专区记录!如果它已经上线并且某些记录没有付费专区,则那些其他脚本适用。如果你给所有记录一个值作为上线的一部分,“有些有,有些没有”的问题永远不会发生

      INSERT INTO wp_meta (article_id, meta_key, meta_value)
      
      SELECT DISTINCT article_id, 'paywall', 'yes'
      FRON wp_meta
      

      将此作为您的上线脚本的一部分

      【讨论】:

        猜你喜欢
        • 2021-07-06
        • 2021-06-04
        • 1970-01-01
        • 2020-03-08
        • 1970-01-01
        • 2020-09-11
        • 1970-01-01
        • 1970-01-01
        • 2019-08-04
        相关资源
        最近更新 更多