【问题标题】:One query to fetch from A, join field values from B as row fields in A and then filter and sort?从 A 获取的一个查询,将 B 中的字段值连接为 A 中的行字段,然后过滤和排序?
【发布时间】:2018-08-10 19:11:53
【问题描述】:

为了创建易于重用和配置的 CMS,我在我的数据库中创建了以下表格。我可以创建具有任意数量的任何命名属性的 PHP 对象数组,并且使用这种结构可以保存它,而无需为每种对象类型制作表格。有点像 Wordpress 对每个自定义项目类型使用“帖子”表。

struct (id, type)

1, 'article'
2, 'article'
3, 'employee'
4, 'article'
...


struct_fields (id, struct_id, sub_id, type, val)

1, 1, 'title', 'string', 'Great article'
2, 1, 'publish_date', 'datetime', '2019-03-02 21:00:00'
3, 1, 'active', 'boolean', 1
4, 1, 'body', 'wysiwyg', '<p>Contents</p>'

5, 2, 'title', 'string', 'Another fantastic article'
6, 2, 'publish_date', 'datetime', '2018-03-01 14:32:17'
7, 2, 'active', 'boolean', 1    
8, 2, 'body', 'wysiwyg', '<p>Cool contents</p>'

9, 3, 'firstname', 'string', 'Jos'
10, 3, 'lastname', 'string', 'Fabre'

11, 4, 'title', 'string', 'This is amazing'
12, 4, 'publish_date', 'datetime', '2018-03-01 19:21:34'
13, 4, 'active', 'boolean', 0   
14, 4, 'body', 'wysiwyg', '<p>Bad content!</p>'
...

我正在努力创建一个可以取出结构列表及其相关字段作为属性的查询。 我不确定这是否可能。 我也想对属性(因此相关表中的字段)进行排序

例如我想创建一个查询,该查询可以获取过去发布日期为最新的 3 篇活动文章。 我已经为 JOIN 和 GROUP BY 苦苦挣扎了好几天了。 对不同类型结构的查询可以按特定字段排序,也可以按另一个字段过滤,或两者兼而有之..

所以,例如对于文章,我希望输出是这样的:

[id, active, publish_date, title, body]

然后过滤活动并在发布日期排序。 id 来自 struct 表,其余字段来自 struct_fields 表中的连接字段。

对于员工来说应该是这样的:

[id, firstname, lastname] 

然后按姓氏ASC、名字ASC排序

在一种情况下,我能够使用 MAX 将 struct_field 属性放入结果行字段中,但如果没有 sql 错误,我无法对它们进行排序

SELECT  struct.id, struct.type, struct.published,
        MAX(CASE WHEN struct_fields.sub_id = 'active' THEN struct_fields.vc1 ELSE NULL END) AS active,
        MAX(CASE WHEN struct_fields.sub_id = 'title' THEN struct_fields.vc1 ELSE NULL END) AS title,
        MAX(CASE WHEN struct_fields.sub_id = 'body' THEN struct_fields.tx1 ELSE NULL END) AS body,
        MAX(CASE WHEN struct_fields.sub_id = 'allday' THEN struct_fields.vc1 ELSE NULL END) AS allday,
        MAX(CASE WHEN struct_fields.sub_id = 'start_datetime' THEN struct_fields.vc1 ELSE NULL END) AS start_datetime,
        MAX(CASE WHEN struct_fields.sub_id = 'end_datetime' THEN struct_fields.vc1 ELSE NULL END) AS end_datetime
FROM struct
INNER JOIN struct_fields ON (struct_fields.struct_id = struct.id)
WHERE struct.type = 'events'
GROUP BY struct.id

帮助!这甚至可以在一个查询中完成吗??

更新:@Nic3500 suggested 发布创建 sql 和一些示例插入,所以它们是:https://pastebin.com/raw/0hPYByDq

【问题讨论】:

  • 如果您发布表创建命令,并插入一些示例数据,我们可以设置该示例并更轻松地处理您的查询。
  • 太好了,这里是:pastebin.com/raw/0hPYByDq
  • ;-) 请在问题中!
  • 我也更新了问题,并故意使用了 pastebin 原始 url,所以问题不会比现在更长 ;-)

标签: mysql sql sorting join


【解决方案1】:

如果您使用别名来订购,可能会发生这种情况

但您也可以使用列位置,例如:

  SELECT  struct.id, struct.type, struct.published,
          MAX(CASE WHEN struct_fields.sub_id = 'active' THEN struct_fields.vc1 ELSE NULL END) AS active,
          MAX(CASE WHEN struct_fields.sub_id = 'title' THEN struct_fields.vc1 ELSE NULL END) AS title,
          MAX(CASE WHEN struct_fields.sub_id = 'body' THEN struct_fields.tx1 ELSE NULL END) AS body,
          MAX(CASE WHEN struct_fields.sub_id = 'allday' THEN struct_fields.vc1 ELSE NULL END) AS allday,
          MAX(CASE WHEN struct_fields.sub_id = 'start_datetime' THEN struct_fields.vc1 ELSE NULL END) AS start_datetime,
          MAX(CASE WHEN struct_fields.sub_id = 'end_datetime' THEN struct_fields.vc1 ELSE NULL END) AS end_datetime
  FROM struct
  INNER JOIN struct_fields ON (struct_fields.struct_id = struct.id)
  WHERE struct.type = 'events'
  GROUP BY struct.id
  order 1,2,3  

通过这种方式,您应该更加缩进,您可以建立一个动态范围或为您的订单设置

【讨论】:

  • 哇,我不知道这是可能的。谢谢。当我尝试在该别名列上过滤/条件时,我仍然遇到错误(列未知)。所以,例如在 WHERE 子句之后添加 AND active = 1 它会给出错误。有没有办法以列号值为条件?
  • 您必须只在职位上工作..而不是在别名上...使用别名 1 是错误的..别名不能是数字..(或以数字开头)..无论如何通过仅解决您的部分需求来使用订单编号..如果您想解决您的问题,您不能使用直接的 SQL 代码,但您应该根据您定义的一组规则动态地构建 SQL 字符串..
  • 构建一个查询最终不会给我一个查询吗?还是我现在误解了“构建查询”的概念?我现在有点远了。如果我使用 HAVING 而不是 WHERE/AND 条件,我可以过滤
  • 这个问题非常广泛.. 涉及几个概念.. 简而言之.. SQL 不允许使用 var 分配对象名称.. 作为列、表...和别名..所以你不能像往常一样传递订单..你可以使用列的位置..来略过这个..但这也是被模仿的..但是你必须认为SQL指令是字符串和服务器端您可以构建您喜欢的字符串..这就是示例 od CMS 的 PHP 框架作为 joomla 或 wordpress.. 使用字符串来动态构建您..需要的查询...希望很清楚。
  • 谢谢。非常清楚。我已经在 PHP 中构建了 SQL 字符串。问题是什么是“唯一”查询
【解决方案2】:

我认为 -可能是因为在得到你的答案后再次积极地深入研究-我设法在这个查询中提出了一个解决方案(在结构类型 = 文章的情况下)

SELECT  struct.id, struct.type, struct.published,
        MAX(CASE WHEN struct_fields.sub_id = 'active' THEN struct_fields.vc1 ELSE NULL END) AS active,
        MAX(CASE WHEN struct_fields.sub_id = 'title' THEN struct_fields.vc1 ELSE NULL END) AS title,
        MAX(CASE WHEN struct_fields.sub_id = 'body' THEN struct_fields.tx1 ELSE NULL END) AS body,
        MAX(CASE WHEN struct_fields.sub_id = 'publish_date' THEN struct_fields.vc1 ELSE NULL END) AS publish_date
FROM struct
INNER JOIN struct_fields ON (struct_fields.struct_id = struct.id)
WHERE struct.type = 'articles'
GROUP BY struct.id
HAVING (active = 1 AND CAST(publish_date as datetime)<NOW() )
ORDER BY publish_date DESC
LIMIT 7

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-24
    • 2015-05-25
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    相关资源
    最近更新 更多