【问题标题】:How to get a single result with columns from multiple records in a single table?如何从单个表中的多个记录中获取单个结果?
【发布时间】:2015-07-26 06:02:37
【问题描述】:

平台:Oracle 10g

我有一张这样的桌子(我们称之为t1):

身份证 | FK_ID |一些值 | SOME_DATE ----+-------+------------+------------ 1 | 101 | 10 | 2013 年 1 月 1 日 2 | 101 | 20 | 2014 年 1 月 1 日 3 | 101 | 30 | 2015 年 1 月 1 日 4 | 102 | 150 | 2013 年 1 月 1 日 5 | 102 | 250 | 2014 年 1 月 1 日 6 | 102 | 350 | 2015 年 1 月 1 日

对于每个FK_ID,我希望显示一个结果,显示两个最近的SOME_VALUEs。那就是:

FK_ID |当前 |以前的 ------+---------+---------- 101 | 30 | 20 102 | 350 | 250

FK_ID 有另一个表(我们称之为t2),这里有一个参考 说这是“当前”记录。所以像这样的表:

身份证 | FK_CURRENT | OTHER_FIELDS ----+------------+------------- 101 | 3 | ... 102 | 6 | ...

我正在尝试使用 有缺陷的子查询连接,如下所示:

SELECT id, curr.some_value as current, prev.some_value as previous FROM t2
  JOIN t1 curr ON t2.fk_current = t1.id 
  JOIN t1 prev ON t1.id = (
    SELECT * FROM (
      SELECT id FROM (
        SELECT id, ROW_NUMBER() OVER (ORDER BY SOME_DATE DESC) as rno FROM t1
          WHERE t1.fk_id = t2.id
      ) WHERE rno = 2
    )
  )

但是t1.fk_id = t2.id 有缺陷(即不会运行),因为(我现在知道)你不能通过父母 字段值到子查询的深度超过一级。

然后我开始想知道公用表表达式 (CTE) 是否是此工具,但后来我没有 使用这些的经验(所以想知道我没有走错路尝试使用它们 - 如果那是工具的话)。

所以我想让我绊倒的关键复杂性是:

  • 通过排序确定前一个值,但同时将其限制为第一条记录(而不是整个表)。 (因此有些复杂的子查询尝试。)

否则,我可以编写一些代码来首先执行查询以获取“当前”值,然后 执行第二个查询以获取“上一个” - 但我很想知道如何用一个单一的来解决这个问题 SQL 查询,因为这似乎是一件很常见的事情(当然是我需要工作的数据库) 与)。

谢谢!

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    尝试使用 LAG 函数的方法:

    SELECT FK_ID , 
           SOME_VALUE as "CURRENT", 
           PREV_VALUE as Previous
    FROM (
        SELECT t1.*,
               lag( some_value ) over (partition by fk_id order by some_date ) prev_value
        FROM t1
    ) x
    JOIN t2 on t2.id = x.fk_id
         and t2.fk_current = x.id
    

    演示:http://sqlfiddle.com/#!4/d3e640/15

    【讨论】:

    • 很好的答案(尤其是支持 sqlfiddle)。工作很愉快,表明我需要阅读并开始理解分析方法。谢谢!
    【解决方案2】:

    试试这个:

    select t1.FK_ID ,t1.SOME_VALUE as CURRENT,
    (select SOME_VALUE from t1 where p1.id2=t1.id and t1.fk_id=p1.fk_id) as PREVIOUS 
    from  t1 inner join
    (
      select t1.fk_id, max(t1.id) as id1,max(t1.id)-1 as id2 from  t1 group by t1.FK_ID 
    ) as p1 on t1.id=p1.id1
    

    【讨论】:

    • 感谢您的建议。忽略日期的有趣想法,但这是一个关键的业务规则;并且您的回答忽略了 FK_CURRENT - 但这很重要(因为带有 ID 的最新项目可能只是草稿记录 - 因此不是最新的)。
    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2014-01-23
    • 2022-10-04
    • 2019-09-06
    • 2017-11-12
    • 1970-01-01
    相关资源
    最近更新 更多