我想基于参数复制一行(默认情况下参数为999)列和ID。例如,在下面的示例中,我们有一个阈值999
,如果一个ID的行包含ParamComp = 999
,另一行包含ParamComp <>999
,则行ParamComp <>999
我们必须使用ParamComp = 999
的ColVal创建一条新记录。
如果ID的行只有ParamComp = 999
,请直接将其加载到目标(不需要重复逻辑)。
此外,如果ID的行只有ParamComp <> 999
,请直接将其加载到目标(不需要复制逻辑)
输入数据
id ParamComp ColVal
1 999 a
1 80 b
2 999 c
3 85 d
目标数据
id ParamComp ColVal
1 999 a
1 80 b
1 80 a
2 999 c
3 85 d
答案 0 :(得分:1)
戈登答案的替代方案(可能会或可能不会更快)是在两排虚拟&#34;表&#34;上进行部分交叉连接,如下所示:
WITH your_table AS (SELECT 1 ID, 999 paramcomp, 'a' colval FROM dual UNION ALL
SELECT 1 ID, 80 paramcomp, 'b' colval FROM dual UNION ALL
SELECT 2 ID, 999 paramcomp, 'c' colval FROM dual UNION ALL
SELECT 3 ID, 85 paramcomp, 'd' colval FROM dual UNION ALL
SELECT 4 ID, 999 paramcomp, 'e' colval FROM dual UNION ALL
SELECT 4 ID, 75 paramcomp, 'f' colval FROM dual UNION ALL
SELECT 4 ID, 70 paramcomp, 'g' colval FROM dual)
-- end of mimicking your table; see SQL below:
SELECT yt.ID,
yt.paramcomp,
case WHEN dummy.id = 1 THEN yt.colval
WHEN dummy.id = 2 THEN yt.paramcomp_999_colval
END colval
FROM (SELECT ID,
paramcomp,
colval,
MAX(CASE WHEN paramcomp = 999 THEN colval END) OVER (PARTITION BY ID) paramcomp_999_colval
FROM your_table) yt
INNER JOIN (SELECT 1 ID FROM dual UNION ALL
SELECT 2 ID FROM dual) dummy ON dummy.id = 1 -- ensures every yt row is returned
OR (dummy.id = 2
AND paramcomp_999_colval IS NOT NULL
AND yt.paramcomp != 999) -- returns an extra row if the 999 paramcomp row exists but the current row isn't 999
ORDER BY yt.ID, yt.paramcomp DESC, yt.colval;
ID PARAMCOMP COLVAL
---------- ---------- ------
1 999 a
1 80 b
1 80 a
2 999 c
3 85 d
4 999 e
4 75 e
4 75 f
4 70 g
4 70 e
这假设每个id只有一个999 paramcomp行(例如,(id,paramcomp)存在唯一约束)。
您必须对此进行测试以及Gordon的答案,以了解哪种方式对您的数据最有效。
ETA:这是Gordon的答案的固定版本,供您与之比较:
select id, paramcomp, colval
from your_table
union all
select id, paramcomp, paramcomp_999_colval colval
from (select yt.*, MAX(CASE WHEN paramcomp = 999 THEN colval END) OVER (PARTITION BY ID) paramcomp_999_colval
from your_table yt
) t
where paramcomp_999_colval IS NOT NULL and paramcomp <> 999
ORDER BY ID, paramcomp DESC, colval;
ETA2:虚拟表使用的更多解释:
如果要复制表中的所有行,则应对具有两行的表/子查询进行交叉连接,如下所示:
SELECT *
FROM your_table yt
CROSS JOIN (SELECT 1 ID FROM dual UNION ALL
SELECT 2 ID FROM dual) dummy;
ID PARAMCOMP COLVAL ID
---------- ---------- ------ ----------
1 999 a 1
1 80 b 1
2 999 c 1
3 85 d 1
4 999 e 1
4 75 f 1
4 70 g 1
1 999 a 2
1 80 b 2
2 999 c 2
3 85 d 2
4 999 e 2
4 75 f 2
4 70 g 2
但是,您并不总是希望显示重复的行,因此您需要进行有选择性的内部联接。我会在最初的答案中打破内部联接,这样你就可以看到它做得更好了。
首先,这是联接的一部分,它确保返回your_table中的每一行:
SELECT *
FROM your_table yt
INNER JOIN (SELECT 1 ID FROM dual UNION ALL
SELECT 2 ID FROM dual) dummy ON dummy.id = 1;
ID PARAMCOMP COLVAL ID
---------- ---------- ------ ----------
1 999 a 1
1 80 b 1
2 999 c 1
3 85 d 1
4 999 e 1
4 75 f 1
4 70 g 1
接下来,这是确保选择性加入的连接部分
SELECT *
FROM your_table yt
INNER JOIN (SELECT 1 ID FROM dual UNION ALL
SELECT 2 ID FROM dual) dummy ON dummy.id = 2
AND yt.paramcomp != 999;
ID PARAMCOMP COLVAL ID
---------- ---------- ------ ----------
1 80 b 2
3 85 d 2
4 75 f 2
4 70 g 2
你可以看到第二部分我们仍然得到id = 3行,这是我们不想要的。所以,在上面的最后一个答案中,我发现paramcomp = 999行的colval是什么,并使用条件最大分析函数返回所有行的colval。然后,我将其添加到第二个连接条件部分,只返回具有999 colval的行(如果它们没有值,那么我们假设999行不存在)。这确实假设colval将始终存在于999行。
答案 1 :(得分:0)
如果我假设999是paramcomp
的最大值,那么分析函数和union all
可以解决问题。遵循您在文本中指定的规则,这将是:
select id, paramcomp, colval
from t
union all
select id, 999 as paramcomp, colval
from (select t.*, max(paramcomp) over (partition by id) as max_paramcomp
from t
) t
where max_paramcomp = 999 and paramcomp <> 999;
对于简单的规则变体,可以轻松修改。