【问题标题】:SQL - ordering results from joined tableSQL - 从连接表中排序结果
【发布时间】:2019-05-11 20:47:49
【问题描述】:

注意:此问题与 WordPress 特定问题有关,但我想从纯 SQL 的角度对此进行“外部观察”:https://wordpress.stackexchange.com/questions/55263/order-posts-by-custom-field-and-if-custom-field-is-empty-return-remaining-posts

假设我们必须具有以下结构的表:

postsID(键),Title

post_metadatapost_ID(FKEY),meta_keymeta_value

我想检索具有以下内容的帖子的 ID 和标题:

  • post_metadata 中的一个条目,其中 key = 'meta_1' 和 meta_value = 'value_1'
  • post_metadata 中添加一个条目,其中key = 'meta_2' 和meta_value = 'value_2'

我想通过meta_key = "meta_3" 的第三个元数据的值对结果进行排序。

现在是棘手的部分:

并非所有帖子在post_metadata 表中都有一个条目,“meta_3”为meta_key。由于我没有按 meta_3 过滤帖子,只是排序,所以我想将这些帖子保留在我的结果中,就好像它们对于这个 meta 有一个空值一样。

我们怎样才能做到这一点?

谢谢

编辑:

现在有 SQL fiddle:https://www.db-fiddle.com/f/kBNaaRFB5xfna5MniuTpaG/1

【问题讨论】:

  • LEFT JOIN... ORDER BY IFNULL(m3.meta_value, '我的空白值')
  • 没能做到这一点
  • 请阅读并采取行动 [ask' 和 minimal reproducible example 并展示您可以做什么以及您尝试了什么。请在您的问题中包含与您的问题相关的任何其他地方的文本。
  • 嗨,我已经使用这个建议设置了一个 SQL 小提琴:db-fiddle.com/f/kBNaaRFB5xfna5MniuTpaG/1

标签: mysql join sql-order-by


【解决方案1】:

也许:

如果存在 meta 3 值,请使用一次左连接来获取 meta 3 值,以确保您保留所有包含 meta1 和 meta2 的帖子都具有所需的值。 然后使用存在,并且必须确保您只获得具有期望值的 meta1 和 2 的记录。

未经测试...

SELECT P.ID, P.Title, PM.Meta_value
FROM Posts P
LEFT JOIN Post_MetaData PM
 on P.ID = PM.Post_ID
and PM.key = 'meta_3'
WHERE exists (SELECT 1 
              FROM post_meta 
              WHERE ((Key 'meta_1' and meta_value = 'Value_1') OR
                    (Key 'meta_2' and meta_value = 'Value_2'))
                and P.ID = Post_ID  --Either here or an AND in the HAVING clause...need to test to know

              GROUP BY  Post_ID
              HAVING count(*) = 2 )
ORDER BY -PM.meta_value desc, P.ID

这确实假设 post_metaData 对每个 Post_ID 的键具有唯一约束。否则我们可以获得值为 a 的 meta_1 和值为 a 的 meta1 并且 count(*) 将为 2;并在结果中错误地返回它。

为了确保最后一个空值,请遵循此方法; MySQL Orderby a number, Nulls last

以 IN 的身份执行此操作....但我认为会慢一些。

SELECT P.ID, P.Title, PM.Meta_value
FROM Posts P
LEFT JOIN Post_MetaData PM
 on P.ID = PM.Post_ID
and PM.key = 'meta_3'
WHERE P.ID in (SELECT Post_meta.Post_ID
              FROM post_meta 
              WHERE ((Key 'meta_1' and meta_value = 'Value_1') OR
                    (Key 'meta_2' and meta_value = 'Value_2'))
              GROUP BY  Post_ID
              HAVING count(*) = 2 )
ORDER BY -PM.meta_value desc, P.ID

【讨论】:

  • 不能成功.. 你能详细说明一下存在子句中的 SELECT 吗?选择 1 ?
  • 您能否将示例帖子表和 post_metaData 放在我们可以使用的 SQLFiddle.com 或 rextester.com 示例中?在那里,我们可以确保它有效。回答您的问题:内部选择称为相关子查询。它返回 key 为 meta_1 和 value_1 或 meta_2 和 value_2 的所有记录。然后它按 post_ID 分组只返回那些同时满足 OR 条件的那些......现在存在确保我们只返回内部查询中存在的帖子和元数据(它就像一个 IN 语句,但通常更快)
  • 您好,感谢您的回复。我已经在这里提出了建议。发生的情况是帖子是部分排序的,但它们始终包含在结果的末尾,即使更改顺序为 DESC:db-fiddle.com/f/kBNaaRFB5xfna5MniuTpaG/1
  • 你希望空值在哪里;最后的? stackoverflow.com/questions/2051602/… 假设这个更新了我的答案。
  • 感谢@xQbert,它几乎可以完美运行。它确实适用于 ASC 排序,但是如果我更改为 DESC,则结果排序不正确。既然你在帖子中提到,实际上同一个元和帖子可以有多个值。一旦我这样做了,它就停止工作了......我已经用你的最后一个答案和示例数据中的这个变化更新了小提琴:db-fiddle.com/f/kBNaaRFB5xfna5MniuTpaG/3
猜你喜欢
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 2023-04-02
相关资源
最近更新 更多