【问题标题】:MySQL sort by calculated value of 2 rowsMySQL按2行的计算值排序
【发布时间】:2010-12-21 21:55:21
【问题描述】:

我正在尝试创建一个 MySQL 语句,该语句将按语句本身计算的值进行排序。我的表格如下所示:

posts
+----+-----------+--------------+
| ID | post_type | post_content |
+----+-----------+--------------+
|  1 |      post |        Hello |
|  2 |      post |        world |
+----+-----------+--------------+

postmeta
+---------+----------+------------+
| post_id | meta_key | meta_value |
+---------+----------+------------+
|       1 |    price |         50 |
|       1 |   retail |        100 |
|       2 |    price |         60 |
|       2 |   retail |         90 |
+---------+----------+------------+

我正在尝试计算一个称为储蓄的值(.5 代表 ID=1.3 代表 ID=2)然后按它排序。这是我到目前为止所拥有的,但我不确定如何跨 2 行进行计算(我发现的所有内容都是关于列之间的计算)。

SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wpostmeta.meta_key = 'Price'
AND wposts.post_type = 'post'
ORDER BY wpostmeta.meta_value DESC

感谢您的帮助!

【问题讨论】:

  • 我知道这没有帮助,但如果您负责数据库,您可能应该对其进行重组,以便 'p​​rice' 和 'retail 是 2 个单独的列......特别是如果那些是仅有的 2 个元键。我认为那些元键类型的东西应该只用于更模糊的“设置”,这样你就不需要运行复杂的查询。
  • 嗯,这是 wordpress 数据库模式,应该足够通用,可以处理几乎所有帖子相关项目的大多数键值对。
  • 当然它足够通用:它重新实现了列。如果可能的话,使用真正的列仍然是一个更好的选择。
  • 是的,WP 的做事方式可能会让您感到痛苦。我认为在 2.5 之前,它将元值放在列中,然后将每个 key=value 对移动到自己的行中。我确信这样做是有充分理由的,但结果是元表必须与其自身连接才能对其进行处理。谢谢你的帖子!

标签: mysql


【解决方案1】:

这是一个简单的联接,它假设 meta_value 是一个数字数据类型,它将计算每个帖子的节省。

select posts.id,
       (retail.meta_value - price.meta_value) * 1.0 / retail.meta_value as savings
  from posts,
       (select * from postmeta where meta_key = 'price') as price,
       (select * from postmeta where meta_key = 'retail') as retail
 where posts.id = price.post_id
   and posts.id = retail.post_id
   and posts.post_type = 'post'
 order by savings;


+----+---------+
| id | savings |
+----+---------+
|  1 | 0.50000 |
|  2 | 0.33333 |
+----+---------+

【讨论】:

  • 我向一位比我有更多 SQL 经验的同事展示了这个帖子,他说你的解决方案是最好的。我试过了,效果很好,谢谢!我刚刚将“select posts.id”更改为“select posts.*”,这样我就可以使用所有其他数据了。顺便说一句, meta_value 不需要是数字,因为减法会正确地进行类型转换(我认为)。再次感谢!
【解决方案2】:

AFAIK 除了使用聚合函数之外,您无法计算“行之间”的事物,在这种情况下这对您没有帮助。

也许您可以改为加入您的表格以便获得一行:

SELECT wposts.*, pri.meta_value / ret.meta_value
FROM $wpdb->posts wposts
INNER JOIN $wpdb->postmeta pri
      ON  pri.post_id = wposts.ID
      AND pri.meta_key = 'price'
INNER JOIN $wpdb->postmeta ret
      ON  ret.post_id = wposts.ID
      AND ret.meta_key = 'retail'
WHERE wposts.post_type = 'post'
ORDER BY pri.meta_value / ret.meta_value

提示:永远不要在 FROM 子句中放置多个表。

【讨论】:

  • 好的,将pri/ret.ID 的错字修正为post_id。 +1
  • “永远不要在 FROM 子句中放置多个表” - QUESTION 显示了所谓的旧 ANSI 连接。语法 ("," 而不是 "INNER JOIN" 本身并没有错,但最佳实践是避免使用它,原因如下:stackoverflow.com/questions/128965/…
【解决方案3】:

编辑:我将您的 0.5 示例输出误解为 50 美分,同样适用于 0.3 = 30 = 90 - 60,而不是您从 (100 - 50) 中获得的百分比/ 100 和 (90 - 60) / 90。也许您仍然会觉得这很有帮助,但它并不能回答所提出的问题。

SELECT wposts.ID,
  SUM(wpostmeta.meta_value * (CASE
    WHEN wpostmeta.meta_key = 'price' THEN -1
    ELSE 1)
  ) AS savings
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wposts.post_type = 'post'
GROUP BY wposts.ID;

关键是对 meta_values 求和,但翻转价格的符号,这样您实际上得到的是零售减去价格,按每个 ID 分组,因此聚合函数 SUM 独立处理每个组。然而,在这里执行所有这些逻辑是否明智是一个不同的问题。 :)

(您可能需要为 MySQL 调整此语法。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-08
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    相关资源
    最近更新 更多