Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
同一表中的行之间的差异(Oracle SQL)_Sql_Oracle - Fatal编程技术网

同一表中的行之间的差异(Oracle SQL)

同一表中的行之间的差异(Oracle SQL),sql,oracle,Sql,Oracle,我一直在比较Oracle SQL中同一个表中的行。我需要得到所有的前/后风格的变化 我有这样的桌子: id date name action 1 01-01-2011 Alex smth 1 05-01-2011 Alexx smth 1 07-01-2011 Alexa smth2 2 02-01-2012 Leo smth3 2 05-01-2012 Leon sm

我一直在比较Oracle SQL中同一个表中的行。我需要得到所有的前/后风格的变化

我有这样的桌子:

id      date        name    action
1       01-01-2011  Alex    smth
1       05-01-2011  Alexx   smth
1       07-01-2011  Alexa   smth2
2       02-01-2012  Leo     smth3
2       05-01-2012  Leon    smth3
我需要得到这个:

id      date        field   before  after
1       05-01-2011  name    Alex    Alexx
1       07-01-2011  name    Alexx   Alexa
1       07-01-2011  action  smth    smth2
2       05-01-2012  name    Leo     Leon
我试着把桌子和它自己连在一起。我找到的方法请在这里找到,它应该可以帮助我将行与下一行进行内部连接,下一行返回无效数字错误

有没有更简单的方法来完成这项任务? 你能帮帮我吗

select t1.id from tablename t1 
inner join tablename t3 on t1.id = t3.id + 1

我首先根据每个id的日期为每一行分配序号,然后将每一行与其下一行自连接。一旦有了这些,您就可以使用几个案例陈述来生成前后数据:

WITH cte AS (
    SELECT id, date, name, action, 
           ROW_NUMBER() OVER (PARTITION BY id ORDER BY date ASC) AS rn
    FROM   mytable
)
SELECT a.id,
       a.date
       CASE WHEN b.name != a.name THEN 'name' ELSE 'action' END AS field,
       CASE WHEN b.name != a.name THEN b.name ELSE b.action END AS before,
       CASE WHEN b.name != a.name THEN a.name ELSE a.action END AS after
FROM   cte b
JOIN   cte a ON b.id = a.id AND b.rn = a.rn + 1

由于您有两个字段要比较,我使用UNION ALL进行了比较,如下所示:

WITH CTE AS (
    SELECT
        ID,
        DATE1,
        NAME1,
        ACTION,
        ROW_NUMBER() OVER(
            PARTITION BY ID
            ORDER BY
                DATE1 ASC
        ) AS RN
    FROM
        MYTABLE
)
-- 
 SELECT
      A.ID,
      B.DATE1,
      'name' AS FIELD,
      A.NAME1   AS BEFORE,
      B.NAME1   AS AFTER
  FROM
      CTE A
      JOIN CTE B ON B.ID = A.ID
                    AND B.RN = A.RN + 1
                        AND B.NAME1 != A.NAME1
  UNION ALL
  SELECT
      A.ID,
      B.DATE1,
      'action' AS FIELD,
      A.ACTION   AS BEFORE,
      B.ACTION   AS AFTER
  FROM
      CTE A
      JOIN CTE B ON B.ID = A.ID
                    AND B.RN = A.RN + 1
                        AND B.ACTION != A.ACTION
  ORDER BY
      ID,
      DATE1
输出:

干杯

您可以使用分析函数:

with t( id, "date", name, action ) as
(
 select 1, date'2011-01-01','Alex','smth' from dual union all
 select 1, date'2011-01-05','Alexx','smth' from dual union all
 select 1, date'2011-01-07','Alexa','smth2' from dual union all
 select 2, date'2012-01-02','Leo','smth3' from dual union all
 select 2, date'2012-01-05','Leon','smth3' from dual 
), t2 as
(
select t.*, 
       lag(name,1,null) over (partition by id order by id, "date") as lg_name,
       lag(action,1,null) over (partition by id order by id, "date") as lg_action
  from t
), t3 as
(
select id, "date", 'name' as field, lg_name as before, name as after
  from t2 where name != lg_name
union all
select id, "date", 'action', lg_action, action 
  from t2 where action != lg_action
)
select * from t3 order by id, "date";

ID  date        FIELD   BEFORE  AFTER
--  ---------   -----   ------  ------
1   05-JAN-11   name    Alex    Alexx
1   07-JAN-11   action  smth    smth2
1   07-JAN-11   name    Alexx   Alexa
2   05-JAN-12   name    Leo     Leon
LAG显然是正确的方法。但是,我首先要取消Pivot:

select id, date, field, prev_value as before, value as after
from (select id, date, field, value,
             lag(value) over (partition by id, field order by date) as prev_value
      from ((select id, "date", 'name' as field, name as value
             from t
            ) union all
            (select id, "date", 'action' as field, action as value
             from t
            ) 
           ) t
      ) t
where prev_value <> value;
在较新版本的Oracle中,可以使用横向联接来简化这一过程:

select id, date, field, prev_value as before, value as after
from (select t.id, t.date, x.field, x.value,
             lag(x.value) over (partition by t.id, x.field order by date) as prev_value
      from t cross join lateral
           (select 'name' as field, name as value from dual union all
            select 'action', action from dual
           ) x
      ) t
where prev_value <> value;

您能解释一下为什么在结果中只有一行:field=action:action smth smth2,但缺少:smth和smth3吗?我无法获取逻辑。因为我只需要选择已更改的字段。如果对于同一条记录,两个字段都在更改给定数据,则此查询仅返回3条记录,则此操作无效。所有案例陈述中也缺少结尾关键字。非常感谢!这是我最需要的,因为我的表中有更多的字段。非常感谢!它也非常有用。抱歉,无法匹配作为第二个答案: