我的当前输出如下图所示。我突出显示了我想删除的记录。
我主要是C#开发人员,所以我的“伪逻辑”来获得我想要的结果如下:
List<int> resultSet = new List<int>();
for(int i = 1; i < table.Length; i++)
{
if((c_id[i] == c_id[i-1])&&
(sub_id[i] < sub_id[i-1]))
{
resultSet.Remove(contact_event_id[i]);
resultSet.Remove(contact_event_id[i-1]);
}
}
基本上,我想要做的是从结果集中删除c_id“配对”的记录。如果出现以下情况,则会将两条记录视为对:
一些重要的注意事项:
我到目前为止的SQL是在下面。注意中子句中的“...”;这是为了使实现尽可能简单。除非真的需要,否则这项任务涉及的逻辑更多,不值得进入。
SELECT * FROM
(
SELECT * FROM e_table
WHERE e_date >= TO_DATE(TRUNC(SYSDATE-1))
AND e_date <= TO_DATE(TRUNC(SYSDATE-1) || ' 23:59:59', 'DD-MON-YY HH24:MI:SS')
AND sub_id IN(2, 1)
) ce
WHERE ce.c_id IN
(
select c_id
from e_table
where e_date >= TO_DATE(TRUNC(SYSDATE-1))
AND e_date <= TO_DATE(TRUNC(SYSDATE-1) || ' 23:59:59', 'DD-MON-YY HH24:MI:SS')
group by c_id
having ...
)
ORDER BY ce_id ASC;
非常感谢任何帮助。如果需要任何详细说明,请告诉我。
请注意,根据我目前提出的逻辑,两个中间记录被认为是对。他们应该被删除;毫无疑问。但是,事后看到如何移除剩余的两行也符合乍一看的要求?它们不应,因为它们在原始输出中不相邻。在这种情况下,我认为毕竟必须使用e_date。但是,重要的是要注意这些对的时间虽然看似相同,但最多可相差一秒。无论如何,仍然需要使用ce_id进行排序,因为按日期排序会导致sub_id不恰当地切换位置。
编辑#2:
上面的图片只是为了表明实现应该在我的查询生成的记录集中进行一次传递。 实际上,sub_id连续两个连续的1是不可能的,正如整篇评论中所解释的那样。
编辑#3
MT0要求的DML:
CREATE TABLE e_table (
ce_id INT,
c_id CHAR(3),
sub_id INT
);
INSERT INTO e_table
SELECT 1, '421', 2 FROM DUAL UNION ALL
SELECT 2, '421', 2 FROM DUAL UNION ALL
SELECT 3, '359', 2 FROM DUAL UNION ALL
SELECT 4, '220', 2 FROM DUAL UNION ALL
SELECT 5, '288', 2 FROM DUAL UNION ALL
SELECT 6, '402', 2 FROM DUAL UNION ALL
SELECT 7, '348', 2 FROM DUAL UNION ALL
SELECT 8, '402', 2 FROM DUAL UNION ALL
SELECT 9, '402', 1 FROM DUAL UNION ALL
SELECT 10, '062', 2 FROM DUAL UNION ALL
SELECT 11, '062', 1 FROM DUAL UNION ALL
SELECT 12, '062', 2 FROM DUAL UNION ALL
SELECT 13, '029', 2 FROM DUAL UNION ALL
SELECT 14, '325', 2 FROM DUAL UNION ALL
SELECT 15, '549', 2 FROM DUAL UNION ALL
SELECT 16, '278', 2 FROM DUAL UNION ALL
SELECT 17, '852', 2 FROM DUAL UNION ALL
SELECT 18, '490', 2 FROM DUAL UNION ALL
SELECT 19, '490', 1 FROM DUAL UNION ALL
SELECT 20, '490', 2 FROM DUAL UNION ALL
SELECT 21, '490', 1 FROM DUAL UNION ALL
SELECT 22, '490', 2 FROM DUAL UNION ALL
SELECT 23, '781', 2 FROM DUAL UNION ALL
SELECT 24, '019', 2 FROM DUAL UNION ALL
SELECT 25, '019', 1 FROM DUAL UNION ALL
SELECT 26, '082', 2 FROM DUAL UNION ALL
SELECT 27, '082', 1 FROM DUAL UNION ALL
SELECT 28, '082', 2 FROM DUAL UNION ALL
SELECT 29, '990', 2 FROM DUAL UNION ALL
SELECT 30, '019', 2 FROM DUAL UNION ALL
SELECT 31, '041', 2 FROM DUAL;
答案 0 :(得分:1)
Oracle安装程序:
CREATE TABLE e_table (
ce_id INT,
c_id CHAR(3),
sub_id INT
);
INSERT INTO e_table
SELECT 1, '421', 2 FROM DUAL UNION ALL
SELECT 2, '421', 2 FROM DUAL UNION ALL
SELECT 3, '359', 2 FROM DUAL UNION ALL
SELECT 4, '220', 2 FROM DUAL UNION ALL
SELECT 5, '288', 2 FROM DUAL UNION ALL
SELECT 6, '402', 2 FROM DUAL UNION ALL
SELECT 7, '348', 2 FROM DUAL UNION ALL
SELECT 8, '402', 2 FROM DUAL UNION ALL
SELECT 9, '402', 1 FROM DUAL UNION ALL
SELECT 10, '152', 2 FROM DUAL UNION ALL
SELECT 11, '062', 2 FROM DUAL UNION ALL
SELECT 12, '062', 1 FROM DUAL UNION ALL
SELECT 13, '062', 2 FROM DUAL UNION ALL
SELECT 14, '029', 2 FROM DUAL UNION ALL
SELECT 15, '062', 1 FROM DUAL UNION ALL
SELECT 16, '325', 2 FROM DUAL UNION ALL
SELECT 17, '549', 2 FROM DUAL UNION ALL
SELECT 18, '001', 2 FROM DUAL UNION ALL
SELECT 19, '002', 2 FROM DUAL UNION ALL
SELECT 20, '002', 1 FROM DUAL UNION ALL
SELECT 21, '001', 1 FROM DUAL UNION ALL
SELECT 22, '001', 2 FROM DUAL;
<强>查询强>:
SELECT *
FROM (
SELECT e.*,
CASE WHEN ( LEAD( c_id ) OVER ( ORDER BY ce_id ) = c_id
AND LEAD( sub_id ) OVER ( ORDER BY ce_id ) < sub_id )
OR ( LAG( c_id ) OVER ( ORDER BY ce_id ) = c_id
AND LAG( sub_id ) OVER ( ORDER BY ce_id ) > sub_id )
THEN 1
ELSE 0
END AS to_delete
FROM e_table e
)
WHERE to_delete = 0;
<强>输出强>:
(第8,9,11,12,19和20行已删除。)
CE_ID C_ID SUB_ID TO_DELETE
---------- ---- ---------- ----------
1 421 2 0
2 421 2 0
3 359 2 0
4 220 2 0
5 288 2 0
6 402 2 0
7 348 2 0
10 152 2 0
13 062 2 0
14 029 2 0
15 062 1 0
16 325 2 0
17 549 2 0
18 001 2 0
21 001 1 0
22 001 2 0
查询2 :
SELECT *
FROM (
SELECT e.*,
CASE WHEN ( LEAD( c_id ) OVER ( PARTITION BY c_id ORDER BY ce_id ) = c_id
AND LEAD( sub_id ) OVER ( PARTITION BY c_id ORDER BY ce_id ) < sub_id )
OR ( LAG( c_id ) OVER ( PARTITION BY c_id ORDER BY ce_id ) = c_id
AND LAG( sub_id ) OVER ( PARTITION BY c_id ORDER BY ce_id ) > sub_id )
THEN 1
ELSE 0
END AS to_delete
FROM e_table e
)
WHERE to_delete = 0
ORDER BY ce_id;
<强>输出强>:
(第8,9,11,12,13,15,18,19,20和21行被移除。)
CE_ID C_ID SUB_ID TO_DELETE
---------- ---- ---------- ----------
1 421 2 0
2 421 2 0
3 359 2 0
4 220 2 0
5 288 2 0
6 402 2 0
7 348 2 0
10 152 2 0
14 029 2 0
16 325 2 0
17 549 2 0
22 001 2 0
答案 1 :(得分:1)
计算ce_id排序的每个c_id的行号。
然后加入上一行并检查sub_id值是否为&gt;或者&lt;。
由于自联接使用union all
从两个表中获取ce_id并从输出中排除这些行。
with x as (
select t.*,row_number() over(partition by c_id order by ce_id) rn from t
)
select * from t
where ce_id not in (
select x1.ce_id
from x x1
join x x2 on x1.c_id = x2.c_id and x1.rn = x2.rn-1
where x1.sub_id > x2.sub_id
union all
select x2.ce_id
from x x1
join x x2 on x1.c_id = x2.c_id and x1.rn = x2.rn-1
where x1.sub_id > x2.sub_id
)
<强> Sample Demo
强>
编辑:要将OP的当前查询包含为cte并使用此答案获取结果,
with t as (/*your query here*/)
, x as (
select t.*,row_number() over(partition by c_id order by ce_id) rn from t
)
select * from t
where ce_id not in (
select x1.ce_id
from x x1
join x x2 on x1.c_id = x2.c_id and x1.rn = x2.rn-1
where x1.sub_id > x2.sub_id
union all
select x2.ce_id
from x x1
join x x2 on x1.c_id = x2.c_id and x1.rn = x2.rn-1
where x1.sub_id > x2.sub_id
)
答案 2 :(得分:0)
您希望过滤掉具有sub_id
两个值的记录。这表明使用分析函数:
select e.*
from (select e.*,
count(distinct sub_id) over (partition by c_id) as numcid
from e_table e
) e
where numcid = 1;
此外,您的示例代码中包含日期逻辑,但问题根本没有提及。
如果以上不是正确的逻辑,我非常确定分析函数可以做你想要的。
编辑:
如果你只是在找一个&#34; 1&#34;在&#34; 2&#34;之后发生,然后使用条件聚合:
select e.c_id
from (select e.c_id,
min(case when sub_id = 1 then e_date end) as sub1_date,
min(case when sub_id = 2 then e_date end) as sub2_date
from e_table e
) e
where sub1_date > sub2_date;
您可以随意修改此内容以获取原始行。