每隔一行的值将显示在新的第3列中

时间:2016-10-20 10:53:43

标签: sql oracle

让我们假设我的数据如下所示: 每隔一行代表一个包含历史数据的表中的旧(前一个值)。

表1:

id     value
------------
1       a
1       b
2       c
2       d
3       a
3       b

我希望得到每隔一行的值,以便出现在新的第3列中,如下所示:

表2:

id    new_value    old_value
------------------------
1       a          b
2       c          d
3       a          b

编辑: 为了清楚起见,生成我希望转换的生成数据的查询的骨架(因此它清楚我已经在使用WITH因此无法使用额外的因为oracle尚未允许WITH元素的嵌套):< / p>

在表1中生成数据的框架代码

with candidates as 
(
        --select list of candidates
)
SELECT * FROM
(
  (
        --select new values
  MINUS
        --select old values
  )
UNION
  (
        --select old values
  MINUS
        --select new values
  )
)
ORDER BY id;

目标是最终只获得一个因旧旧值而改变的ID列表。

提前致谢。

3 个答案:

答案 0 :(得分:3)

使用CTE

$arr = array();
foreach($_POST as $key=>$value){
    if($key == "load" || strpos("id",$key) !== false){
        continue;
    }
    $data = file_get_contents('http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=C5DF6B05C9770667C1E3138EE69A8301&steamid='.$value.'&format=json');
    $json = json_decode($data, TRUE);
    array_push($arr,$json);
}

答案 1 :(得分:2)

假设还有一些其他列定义了&#34; order&#34;在新旧值出现的情况下,您可以这样做:

select t1.id, t1.value as old_value, t2.value as new_value
from the_table t1
  join the_table t2 on t1.id = t2.id and t1.sort_order < t2.sort_order

但是 有一些列可以区分被认为是&#34; old&#34;从被认为是&#34;新&#34;。

答案 2 :(得分:2)

很有可能整个查询可以用更简单的方式编写。只需将id上的旧值和新值一起加入中间结果,将它们放在两个不同的列中,而不是将它们合并到同一列中。

WITH
candidates
AS
(
    --select list of candidates
)
,CTE_NewValues
AS
(
    --select new values
    select id, value AS new_value
    FROM candidates
    WHERE ...
    -- assumes id is unique, one row per id
)
,CTE_OldValues
AS
(
    --select old values
    select id, value AS old_value
    FROM candidates
    WHERE ...
    -- assumes id is unique, one row per id
)
SELECT
    CTE_NewValues.id
    ,CTE_NewValues.new_value
    ,CTE_OldValues.old_value
FROM
    CTE_NewValues
    INNER JOIN CTE_OldValues ON CTE_NewValues.id = CTE_OldValues.id
WHERE
    CTE_NewValues.new_value <> CTE_OldValues.old_value
ORDER BY
    CTE_NewValues.id;

如果我们在问题中坚持查询的骨架,那么还有很多方法可以做到。自联接的效率可能低于使用ROW_NUMBERLEAD等分析函数。

仅按id排序不足以明确定义哪个值是新的还是旧的。你需要一些额外的列来解决它。

你没有“嵌套”WITH(公用表表达式),你将它们“链接”起来。像下面这样的东西。在执行此操作时,请确保添加sort_order列,以便能够区分旧值和新值,如果您还没有类似的列。

WITH
candidates 
AS
(
    --select list of candidates
)
,CTE_YourQuery
AS
(
    SELECT * FROM
    (
        (
        --select new values
        select 1 AS sort_order, id, value
        MINUS
        --select old values
        select 1 AS sort_order, id, value
        )
    UNION ALL
        (
        --select old values
        select 2 AS sort_order, id, value
        MINUS
        --select new values
        select 2 AS sort_order, id, value
        )
    )
)
,CTE_RowNumber
AS
(
    SELECT
        id
        ,value AS new_value
        ,ROW_NUMBER() OVER (PARTITION BY id ORDER BY sort_order) AS rn
        ,LEAD(value) OVER (PARTITION BY id ORDER BY sort_order) AS old_value
    FROM CTE_YourQuery
)
SELECT
    id
    ,new_value
    ,old_value
FROM CTE_RowNumber
WHERE rn = 1
ORDER BY id;