【问题标题】:MYSQL Group if parent field is not emptyMYSQL Group 如果父字段不为空
【发布时间】:2018-09-02 05:43:17
【问题描述】:

如果父级不为空,有没有办法将行组合在一起

我先解释一下数据库:

-----------------------------------------------------
ID    |    NAME    |       date       |    PARENT ID
-----------------------------------------------------
1    | John Doe   |    2018-01-12    |
2    | Doe John   |    2018-01-12    |    
3    | Doe John   |    2018-02-12    |        2
4    | Doe John   |    2018-03-22    |        2

现在我想要的是得到一个这样的列表:

--------------------------------------------------------------
ID    |    NAME    |           date          |    PARENT ID
-------------------------------------------------------------
1    | John Doe    |       2018-01-12        |
2    | Doe John    | 2018-01-12 / 2018-03-22 |    

我尝试过这样的事情:

SELECT *, CONCAT(parentID)
FROM names
GROUP BY parentID;

但是结果只有具有 parentID 的结果,我想显示没有 parentID 的结果并将具有 parentID 的结果分组到 ID

【问题讨论】:

  • 你需要解释得更好,这看起来更像是需要在 parent_id IS NULL 上使用 WHERE 子句,而不是分组问题......
  • date 列的条目是 CONCAT(MIN(date), ' / ', MAX(date)) 组吗? (+日期格式...)
  • 不完全清楚,至少对我来说,date 是如何计算的。它是否包含节点的日期及其子节点的日期?如果是,那么为什么Doe John 不包含日期2018-02-12
  • SELECT * .... GROUP BY parentID 正在自找麻烦,因为它不是 ansi 有效的 group by 查询,这意味着结果可能与分组列 parentID 无关。阅读psce.com/en/blog/2012/05/15/…
  • 我已经在里面放了一些示例数据,我需要它作为我正在写的预订代码。所以有人可以预订更多的日期,我想结合它是否有一个父母的父母ID

标签: mysql concat


【解决方案1】:

试试这个:

SELECT MAX(dates.id), MAX(dates.name), MAX(dates.date), MAX(a.date)
FROM dates
LEFT JOIN dates a ON a.parentID = dates.id
WHERE dates.parentID IS NULL GROUP BY a.parentID;

您遇到的问题是您需要一种方法来连接来自具有对应于行 ID 的 parentID 的行的数据。使用此查询,我们过滤行以仅显示没有 parentID 的行,然后抓取所有 parentID 等于当前行 ID 的行。使用 max 可确保正确使用 group by 并显示您的示例中似乎要求的内容。

【讨论】:

    【解决方案2】:

    当 parentID 为 null 时,您可以基于 ifnull 使用 group by 使用 ID

    SELECT *, CONCAT(parentID)
    FROM names
    GROUP BY ifnull(parentID, ID);
    

    【讨论】:

      【解决方案3】:

      诀窍是使用LEFT JOIN 加入表自身,使用初始表作为父表,将连接表作为子表。

      SELECT
          *
      FROM
        users as parents
        LEFT JOIN users as children ON parents.id = children.parent_id
      

      LEFT JOIN 将保留初始表中的所有行(在本例中为 parents),并仅将连接表中的行(在本例中为 children)添加到它,如果加入是可能的。否则只会添加 NULL 值。

      | id |   name     |    date    | parent_id |   id   |    name     |    date    | parent_id |
      |  2 |  Doe John  | 2018-01-12 |   (null)  |    3   |   Bill John | 2018-02-12 |     2     |
      |  2 |  Doe John  | 2018-01-12 |   (null)  |    4   |   Elmo John | 2018-03-22 |     2     |
      |  1 |  John Doe  | 2018-01-12 |   (null)  | (null) |    (null)   |   (null)   |   (null)  |
      |  3 |  Bill John | 2018-02-12 |     2     | (null) |    (null)   |   (null)   |   (null)  |
      |  4 |  Elmo John | 2018-03-22 |     2     | (null) |    (null)   |   (null)   |   (null)  |
      

      如果这样做了,每个 parent 将恰好有一行,而没有 children,每个 parent 的行数一样多>child,因为该 parentchildren 存在。

      因此,可以在parents.id 列上使用GROUP BY,因为对于具有相同父级的每个子级父级是相等的 并且没有 children 的每个 parent 都存在一行。要从 父母 中过滤出那些人,他们是孩子而不是父母,可以添加 WHERE 子句 parents.parent_id IS NULL

      SELECT
          parents.id
      FROM
        users as parents
        LEFT JOIN users as children ON parents.id = children.parent_id
      WHERE
        parents.parent_id IS NULL
      GROUP BY
        parents.id
      

      要获得所需的date,您必须使用聚合函数MIN()MAX() 来计算日期间隔的开始日期和结束日期。

      函数COALESCE() 是必需的,因为LEFT JOIN 可能会导致您拥有NULL 值。它将输出第一个提供的参数,即不是NULL。在此示例中,CONCAT 的结果是 NULL,如果 children.date 和因此 MIN(children.date) 和因此 LEAST(...) 返回 NULL。在这种情况下,将使用第二个值 paprents.id

      SELECT
        parents.id,
        parents.name,
        COALESCE(
          CONCAT(
            LEAST(parents.date, MIN(children.date)), 
            ' / ', 
            GREATEST(parents.date, MAX(children.date))
          ), 
          parents.date
        ) as 'date'
      FROM
        users as parents
        LEFT JOIN users as children ON parents.id = children.parent_id
      WHERE
        parents.parent_id IS NULL
      GROUP BY
        parents.id,
        parents.name, -- Just added for output without aggregation
        parents.date -- Just added for output without aggregation
      

      Running example on sqlfiddle.com

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-10
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多