【问题标题】:Split one SQL column into multiple based on condition根据条件将一个 SQL 列拆分为多个
【发布时间】:2023-01-10 23:49:11
【问题描述】:

我需要根据某些条件将一列分成两列。这是表格的示例:

id | title
----------
1  | one
2  | two
3  | three
4  | four

所以,我想要一个包含两列的视图,例如id1id2,第一列将包含小于 3 的 ID,第二列 - 其余 ID,结果应该是连续的。预期结果是

id1 | id2
----------
1   | 3
2   | 4

【问题讨论】:

  • 这是真实的数据/愿望吗?或者这只是一种简化更复杂问题的方法?
  • @gotqn 是的,它是简化的描述,但目标是按条件将一列分成两列,没有任何额外的要求/列。我得到了两组相同大小的数据,需要相应地拆分它们。如果我遗漏了一些重要的东西,请告诉我

标签: mysql sql


【解决方案1】:

这与 mysql 5 兼容:

select 
  MAX(case when id <= 2 then id END) AS id1,
  MAX(case when id > 2 then id END) AS id2
from (
  select 
  id,
  IF(id%2, 1, 0) as gp
  from TABLE1
) as s
GROUP BY gp
ORDER BY id1,id2

【讨论】:

    【解决方案2】:

    在没有看到更多数据的情况下,确切的要求并不完全清楚。这是使用 ROW_NUMBER() 和旋转逻辑的一种解释:

    WITH cte AS (
        SELECT *, ROW_NUMBER() OVER (ORDER BY id) - 1 AS rn
        FROM yourTable
    )
    
    SELECT
        MAX(CASE WHEN FLOOR(rn / 2) = 0 THEN id END) AS id1,
        MAX(CASE WHEN FLOOR(rn / 2) = 1 THEN id END) AS id2
    FROM cte
    GROUP BY rn % 2
    ORDER BY 1;
    

    这是一个有效的demo

    【讨论】:

    • 在OP给出的示例中,这不会导致一列中出现1和3,而另一列中出现2和4吗?
    • @JensSchauder 不,您错误地阅读了我的回答。在此处查看演示:dbfiddle.uk/MXSXXF6Q
    • 好的,我现在明白了。我有点错过了MAX
    【解决方案3】:

    这应该可以解决问题。

    select small.id as id1, big.id as id2
    from(
      select id, title, 
        row_number() over (order by id) rn
      from demo
      where id < 3
    ) small
    join (
      select id, title, 
        row_number() over (order by id) rn 
      from demo
      where id >=3
    ) big
    on small.rn = big.rn
    
    

    为简单起见,我使用了JOIN,如果您不能保证两个部分具有相同的行数,您可能必须使用LEFTRIGHTFULL OUTER JOIN

    我放了一个working example on dbfiddle

    与使用 GROUP BY 的变体相比,这种方法是可以在最终查询中轻松使用所有其他列。

    【讨论】:

    • 您需要 row_number 而不是 rownumber
    • @TimBiegeleisen 正确。感谢您的注意。我修好了它。
    【解决方案4】:

    通常对于 N 行的表

    WITH yourTable AS (
        SELECT 1 AS id, 'one' AS title UNION ALL
        SELECT 2, 'two' UNION ALL
        SELECT 3, 'three' UNION ALL
        SELECT 4, 'four' UNION ALL
        SELECT 5, 'five' UNION ALL
        SELECT 6, 'six' UNION ALL
        SELECT 7, 'seven'
    ),
    cte AS (
        SELECT *, 
          ROW_NUMBER() OVER(ORDER BY id) - 1 AS rn,
          count(*) over() cnt
        FROM yourTable
    )
    SELECT 
        max(CASE WHEN rn < cnt / 2 THEN id END) AS id1,
        max(CASE WHEN rn >=cnt / 2 THEN id END) AS id2
    FROM cte
    GROUP BY rn % round(cnt/2) 
    ORDER BY 1;
    

    退货

    id1 id2
    1   5
    2   6
    3   7
    4   null
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      相关资源
      最近更新 更多