【问题标题】:logic to create more rows in sql在 sql 中创建更多行的逻辑
【发布时间】:2021-02-05 14:34:44
【问题描述】:

我有一个想要转换为预期表格的 table1。

  • 列的预期表逻辑:
  • cal:来自table1的cal。 ID来自table1的ID。
  • 代码:这取决于我们是否在 f_a 中有一个值,然后我们用 fp 作为代码创建一个新记录。与它相对应,我们检查是否填充了 f_a,如果是,则我们从 f_a 中获取该日期并放入同一 ID 的 Al 列中。我们还检查是否填充了 f_pl,如果是,则我们从中获取日期并将其放入 pl 列中。
  • 如果代码是 lp,那么我们检查是否填充了 l_a,然后我们获取该日期并将该日期放入该代码和 Id 的 Al 中。此外,我们检查是否填充了 lpl,如果是,则我们将该日期放入 pl。

我只是 SQL 的初学者,所以对于如何开始使用它对我来说有点不知所措。请发布一些解决方案。

表1:

ID  f_a            l_a           f_pl       lpl               cal
CNT 6/20/2018      6/28/2018                6/28/2018         1/31/2020

预期输出:

ID  Cal             code          pl            Al 
CNT 1/31/2020       lp        6/28/2018   6/28/2018 
CNT 1/31/2020       fp                    6/20/2018 

更新: 我在表中有更多的 ID,所以不是 CNT 是唯一的 ID。如果我使用 unpivot,那么它应该对所有 ID 遵循相同的逻辑。

【问题讨论】:

  • 请用您正在运行的数据库标记您的问题:mysql、oracle、sqlserver...?
  • 请注意,表格有,而不是记录。

标签: sql oracle union unpivot lateral-join


【解决方案1】:

请试试这个不依赖版本的脚本:

-- Here we select columns foom source table. Please change the names if they are different
with r as (
  select
    ID,
    f_a,
    l_a,
    f_pl,
    lpl, -- Here not sure if example is wrong or no underscore in column deffinition
    cal
  from table_1 --  Please put real table name here
)
select * from (
select r.id, r.cal, 'lp' as code, r.l_pl as pl, l_a as ai
from r
where r.l_a is not null
union all
select r1.id, r1.cal, 'pl', r1.f_pl, r1.f_a 
from r r1
where r1.f_a is not null
)
order by id, cal, code;

【讨论】:

  • 我对您的代码进行了一些更改,它可以正常工作。非常感谢。
  • @KSp - 谢谢,我的错。忘记别名了。脚本已更新。
【解决方案2】:

您可以将UNPIVOT 用于多个列,然后对日期进行所需的检查:

with a as (
  select
    'CNT' as ID,
    date '2018-06-20' as f_a,
    date '2018-06-28' as l_a,
    cast(null as date) as f_pl,
    date '2018-06-28' as l_pl,
    date '2020-01-31' as cal
  from dual
)
select *
from a
unpivot(
  (pl, al) for code in ((l_pl, l_a) as 'lp', (f_pl, f_a) as 'fp')
) up
ID  | CAL       | CODE | PL        | AL
CNT | 31-JAN-07 | lp   | 28-JUN-18 | 28-JUN-18
CNT | 31-JAN-07 | fp   |           | 20-JUN-18

Working example here.

【讨论】:

  • 请注意,我并不想只获取一个日期集的值,我必须申请整个表格。
  • @KSp 你是什么意思? Unpivot 对数据集和表一无所知,它只是将列反透视为行。需要澄清你的陈述
  • 你是说如果我的表中有更多不同id的行,它遵循相同的逻辑?
  • @KSp 最好在示例中提供更多数据并自行测试,但是是的,它会这样做,因为 unpivot 保持其他字段不变。只需获取字段(或字段组),将其名称转换为 UNPIVOT 的 IN 部分中声明的值,并将该列的值放入 UNPIVOT 的 FOR 部分之前声明的相应列的值。对于每个列组(在 IN 之后的括号中),它会生成新行。最好阅读文档或示例:blogs.oracle.com/sql/…
【解决方案3】:

这是一个关于如何unpivot 列到行的问题。在 Oracle 中,我建议使用横向连接:

select t.id, t.cal, x.*
from mytable t
cross apply (
    select 'lp' as code, t.lpl as pl, l_a as al from dual
    union all
    select 'fp', t.f_pl, t.f_a from dual
) x

此语法在 Oracle 12.1 及更高版本中可用。在早期版本中,您将使用union all

select id, cal, 'lp' as code, lpl as pl, l_a as al from mytable
union all
select id, cal, 'lp' as code, 'fp', f_pl, f_a from mytable

【讨论】:

  • 为什么不将 (f_a, f_pl) 取消旋转为 'fp',将 (l_a, l_pl) 取消旋转为 'lp'?横向更快/更少资源消耗?就可读性而言,我认为横向连接需要更多的精力来阅读并从代码中提取真正的价值
  • @GMB 结果确实拆分为两条记录和代码列作为 lp 两次在相同的值而不是 fp 上,fp 显示在一个新字段中。
  • 查看更新后的输出,这样您就可以看到我从您的查询中得到了什么。
  • @KSp 这很奇怪,因为我在小提琴中使用了这段代码(将 mytable 替换为其中的 a )并得到与 UNPIVOD 相同的输出。此外,您无法获得这些结果,因为他的脚本中没有名为“field1”的字段。
  • @KSp:我为您提供的查询不可能生成您正在显示的输出。这是一个 db fiddle:dbfiddle.uk/…。您可以看到这是您期望的输出。
猜你喜欢
  • 2016-05-08
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-24
相关资源
最近更新 更多