让我们假设我的数据如下所示: 每隔一行代表一个包含历史数据的表中的旧(前一个值)。
表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列表。
提前致谢。
答案 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_NUMBER
和LEAD
等分析函数。
仅按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;