I need to find the difference between the rows c2 in the below table
SEQ_ID Priv_ID Common_ID Source_ID C1 C2
------ -------- --------- --------- -- ---
1 1 C001 S1 abc 32331299300
2 1 C001 S1 def 12656678121
3 1 C001 S1 ghi 8966492700
4 1 C001 S2 abc 32331292233
5 1 C001 S2 ghi 8966492700
6 1 C001 S2 def 12656672000
expected output should be as below,
SEQ_ID Priv_ID Common_ID C1 C2
------ -------- --------- -- ---
1 1 C001 abc 7067
2 1 C001 def 6121
3 1 C001 ghi 0
Please assist.
How about this? I didn't use columns that are the same for all rows (so they don't make any difference).
SQL> with test (seq_id, source_id, c1, c2) as
2 (select 1, 's1', 'abc', 32331299300 from dual union all
3 select 2, 's1', 'def', 12656678121 from dual union all
4 select 3, 's1', 'ghi', 8966492700 from dual union all
5 select 4, 's2', 'abc', 32331292233 from dual union all
6 select 5, 's2', 'ghi', 8966492700 from dual union all
7 select 6, 's2', 'def', 12656672000 from dual
8 )
9 select min(seq_id) seq_id,
10 c1,
11 max(case when source_id = 's1' then c2 end) +
12 max(case when source_id = 's2' then -c2 end) c2
13 from test
14 group by c1
15 order by 1;
SEQ_ID C1 C2
---------- --- ----------
1 abc 7067
2 def 6121
3 ghi 0
SQL>
Hmmm . . . One method would be conditional aggregation. But the key is row_number():
select Priv_ID, Common_ID, c1,
max(case when source_ID = 'S1' then c2
when source_ID = 'S2' then -c2
end) as diff
from (select t.*,
row_number() over (partition by Priv_ID, Common_ID, c1 order by seq_id) as seqnum
from t
) t
group by Priv_ID, Common_ID, c1
Related
I've sql query setup that produces this output:
ID
ID1
ID2
1
123
null
1
234
null
1
456
null
1
null
789
1
null
012
I need the output to be following:
ID
ID1
ID2
1
123
789
1
234
012
1
456
null
Any help will be greatly appreciated.
I have a feeling that this (what you want) should be already done. If that's not possible, see if this helps. Read comments within code.
SQL> with test (id, id1, id2) as
2 -- result produced by current query
3 (select 1, 123, null from dual union all
4 select 1, 234, null from dual union all
5 select 1, 456, null from dual union all
6 select 1, null, '789' from dual union all
7 select 1, null, '012' from dual
8 ),
9 taba as
10 -- ID1 and row ordinal number (for joining purposes)
11 (select id, id1, row_number() over (order by id1) rn
12 from test
13 ),
14 tabb as
15 -- ID2 and row ordinal number (for joining purposes)
16 (select id, id2, row_number() over (order by id2) rn
17 from test
18 )
19 -- join them on ID and RN
20 select a.id, a.id1, b.id2
21 from taba a join tabb b on a.id = b.id and a.rn = b.rn
22 where a.id1 is not null
23 order by a.id, a.id1, b.id2;
ID ID1 ID2
---------- ---------- ---
1 123 012
1 234 789
1 456
SQL>
SELECT ID, ID1, ID2
FROM table1
WHERE ID1 IS NOT NULL
I think that you can use case statement.
look here: Multiple conditions with CASE statements
If after that you question continue, don't worry, call me.
Below are the tables that i work on -
table_ctrl_result -
seq_id req_id ctrl_id c1 c2 status
1 1 C001 DES 380 NULL
2 1 C001 ABC 0 NULL
3 1 C001 EDC 0 NULL
TABLE_CTRL_MSTR -
ctrl_id tolerance symbol
c001 1000 <
Below is the expected result,
seq_id req_id ctrl_id c1 c2 status
1 1 C001 DES 380 PASS
2 1 C001 ABC 0 PASS
3 1 C001 EDC 0 PASS
I am using the query thats mentioned in the comment , but I am getting the below result.,
seq_id req_id ctrl_id c1 c2 status
1 1 C001 DES 380 PASS
2 1 C001 ABC 0 FAIL
3 1 C001 EDC 0 FAIL
SQL:
update ca_demo.table_ctrl_result a
set a.STATUS = (
select
(case
when b.symbol = '>' and a.c2 > b.tolerance or b.symbol = '<' and a.c2 < b.tolerance or b.symbol = '=' and a.c2 = b.tolerance
then 'PASS'
else 'FAIL'
end)
from ca_demo.table_ctrl_mstr b
where a.ctrl_id = b.ctrl_id
);
I'm missing something. Please assist.
Test case:
SQL> create table ctrl_result
2 (seq_id number,
3 ctrl_id varchar2(4),
4 c1 varchar2(3),
5 c2 number,
6 status varchar2(5));
Table created.
SQL> create table ctrl_mstr
2 (ctrl_id varchar2(4),
3 tolerance number,
4 symbol varchar2(2));
Table created.
SQL> insert into ctrl_result
2 select 1, 'C001', 'DES', 380, null from dual union all
3 select 2, 'C001', 'ABC', 0, null from dual union all
4 select 3, 'C001', 'EDC', 0, null from dual union all
5 select 4, 'C002', 'XXX', 500, null from dual union all
6 select 5, 'C002', 'YYY', 100, null from dual;
5 rows created.
SQL> insert into ctrl_mstr
2 select 'C001', 1000, '<' from dual union all
3 select 'C002', 200, '>' from dual;
2 rows created.
Some querying & the result:
SQL> merge into ctrl_result c
2 using (select r.seq_id, r.ctrl_id, r.c2,
3 m.tolerance, m.symbol,
4 --
5 case when m.symbol = '<' and r.c2 < m.tolerance then 'PASS'
6 when m.symbol = '<' and r.c2 >= m.tolerance then 'FAIL'
7 when m.symbol = '>' and r.c2 > m.tolerance then 'PASS'
8 when m.symbol = '>' and r.c2 <= m.tolerance then 'FAIL'
9 else 'NONE'
10 end status
11 from ctrl_result r join ctrl_mstr m on m.ctrl_id = r.ctrl_id
12 ) x
13 on (c.seq_id = x.seq_id)
14 when matched then update set c.status = x.status;
5 rows merged.
SQL> select * From ctrl_Result order by seq_id;
SEQ_ID CTRL C1 C2 STATU
---------- ---- --- ---------- -----
1 C001 DES 380 PASS
2 C001 ABC 0 PASS
3 C001 EDC 0 PASS
4 C002 XXX 500 PASS
5 C002 YYY 100 FAIL
SQL>
I am having trouble trying to find an appropriate query(SQL-SERVER) for selecting records with condition however, the table I will be using has more than 100,000 rows and more than 20 columns.
So I need a code that satisfies the following condition:
1.)If [policy] and [plan] column is unique between rows then I will select that record
2.)If [policy] and [plan] return 2 or more rows then I will select the record which 'code' column isn't 999
3.)In some cases the unwanted rows may not have '999' in [code] column but may be other specifics
In other words, I would like to get row number 1,2,4,5,7.
Here is an example of what the table looks like
row #|policy|plan|code
-----------------------
1 | a | aa |111
-----------------------
2 | b | bb |112
-----------------------
3 | b | bb |999
-----------------------
4 | c | cc |111
-----------------------
5 | c | cc |112
-----------------------
6 | c | cc |999
-----------------------
7 | d | dd |999
-----------------------
I'm expecting to see something like
row #|policy|plan|code
-----------------------
1 | a | aa |111
-----------------------
2 | b | bb |112
-----------------------
4 | c | cc |111
-----------------------
5 | c | cc |112
-----------------------
7 | d | dd |999
-----------------------
Thank you in advance
This sounds like a prioritization query. You an use row_number():
select t.*
from (select t.*,
row_number() over (partition by policy, plan
order by code
) as seqnum
from t
) t
where seqnum = 1;
The expected output makes this a bit clearer:
select t.*
from (select t.*,
rank() over (partition by policy, plan
order by (case when code = 999 then 1 else 2 end) desc
) as seqnum
from t
) t
where seqnum = 1;
The OP wants all codes that are not 999 unless the only codes are 999. So, another approach is:
select t.*
from t
where t.code <> 999
union all
select t.*
from t
where t.code = 999 and
not exists (select 1
from t t2
where t2.policy = t.policy and t2.plan = t.plan and
t2.code <> 999
);
May be you want this (eliminate the last row if more than one)?
select t.*
from (select t.*
, row_number() over (partition by policy, plan
order by code desc
) AS RN
, COUNT(*) over (partition by policy, plan) AS RC
from t
) t
where RN > 1 OR RN=RC;
Output:
row policy plan code RN RC
1 1 a aa 111 1 1
2 2 b bb 112 2 2
3 5 c cc 112 2 3
4 4 c cc 111 3 3
5 7 d dd 999 1 1
CREATE TABLE #Table2
([row] int, [policy] varchar(1), [plan] varchar(2), [code] int)
;
INSERT INTO #Table2
([row], [policy], [plan], [code])
VALUES
(1, 'a', 'aa', 111),
(2, 'b', 'bb', 112),
(3, 'b', 'bb', 999),
(4, 'c', 'cc', 111),
(5, 'c', 'cc', 112),
(6, 'c', 'cc', 999),
(7, 'd', 'dd', 999)
;
with cte
as
(
select *,
row_number() over (partition by policy, [plan]
order by code
) as seqnum
from #Table2
)
select [row], [policy], [plan], [code] from cte where seqnum=1
Assume the following table:
TableA:
ID GroupName SomeValue
1 C 1
2 C 1
2 B 1
2 A 1
I need to construct a query that selects the following result:
ID GroupName SomeValue
1 C 1
1 B 0
1 A 0
2 C 1
2 B 1
2 A 1
The GroupName is actually derived from TableA column's CASE expression and can take only 3 values: A, B, C.
Are the analytic functions the way to go?
EDIT
Sorry, for not mentioning it, but the ID could consist of multiple columns. Consider this example:
ID1 ID2 GroupName SomeValue
1 1 C 1
1 2 C 1
2 2 C 1
2 2 B 1
2 2 A 1
I need to pad SomeValue with 0 for each unique combination ID1+ID2. So the result should be like this:
ID1 ID2 GroupName SomeValue
1 1 C 1
1 1 B 0
1 1 A 0
1 2 C 1
1 2 B 0
1 2 A 0
2 2 C 1
2 2 B 1
2 2 A 1
EDIT2
Seems like solution, proposed by #Laurence should work even for multiple-column 'ID'. I couldn't rewrite the query proposed by #Nicholas Krasnov to conform to this requirement. But could somebody compare these solutions performance-wise? Will the analytic function work faster than 'cross join + left outer join'?
To fill in gaps, you could write a similar query using partition by clause of outer join:
SQL> with t1(ID,GroupName,SomeValue) as
2 (
3 select 1, 'C', 1 from dual union all
4 select 2, 'C', 1 from dual union all
5 select 2, 'B', 1 from dual union all
6 select 2, 'A', 1 from dual
7 ),
8 groups(group_name) as(
9 select 'A' from dual union all
10 select 'B' from dual union all
11 select 'C' from dual
12 )
13 select t1.ID
14 , g.group_name
15 , nvl(SomeValue, 0) SomeValue
16 from t1
17 partition by (t1.Id)
18 right outer join groups g
19 on (t1.GroupName = g.group_name)
20 order by t1.ID asc, g.group_name desc
21 ;
ID GROUP_NAME SOMEVALUE
---------- ---------- ----------
1 C 1
1 B 0
1 A 0
2 C 1
2 B 1
2 A 1
6 rows selected
UPDATE: Response to the comment.
Specify ID2 column in the partition by clause as well:
SQL> with t1(ID1, ID2, GroupName,SomeValue) as
2 (
3 select 1, 1, 'C', 1 from dual union all
4 select 1, 2, 'C', 1 from dual union all
5 select 2, 2, 'C', 1 from dual union all
6 select 2, 2, 'B', 1 from dual union all
7 select 2, 2, 'A', 1 from dual
8 ),
9 groups(group_name) as(
10 select 'A' from dual union all
11 select 'B' from dual union all
12 select 'C' from dual
13 )
14 select t1.ID1
15 , t1.ID2
16 , g.group_name
17 , nvl(SomeValue, 0) SomeValue
18 from t1
19 partition by (t1.Id1, t1.Id2)
20 right outer join groups g
21 on (t1.GroupName = g.group_name)
22 order by t1.ID1, t1.ID2 asc , g.group_name desc
23 ;
ID1 ID2 GROUP_NAME SOMEVALUE
---------- ---------- ---------- ----------
1 1 C 1
1 1 B 0
1 1 A 0
1 2 C 1
1 2 B 0
1 2 A 0
2 2 C 1
2 2 B 1
2 2 A 1
9 rows selected
Select
i.Id1,
i.Id2,
g.GroupName,
Coalesce(a.SomeValue, 0) As SomeValue
From
(select distinct ID1, ID2 from TableA) as i
cross join
(select distinct GroupName from TableA) as g
left outer join
tableA a
on i.ID = a.ID and g.GroupName = a.GroupName
Order By
1,
2,
3 Desc
I have a table like this
C1 C2 C3 Code
1 2 3 33
1 2 3 34
2 4 1 14
1 2 3 14
i want to select only those record whose code is appearing only in single row. ie, in this case rows with code 33 and 34.. as they appear only once in this table.
How can i write a query for that
If you want only one pass over your data, then you can use this query:
SQL> create table mytable (c1,c2,c3,code)
2 as
3 select 1, 2, 3, 33 from dual union all
4 select 1, 2, 3, 34 from dual union all
5 select 2, 4, 1, 14 from dual union all
6 select 1, 2, 3, 14 from dual
7 /
Table created.
SQL> set autotrace on
SQL> select max(c1) c1
2 , max(c2) c2
3 , max(c3) c3
4 , code
5 from mytable
6 group by code
7 having count(*) = 1
8 /
C1 C2 C3 CODE
---------- ---------- ---------- ----------
1 2 3 33
1 2 3 34
2 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 FILTER
2 1 SORT (GROUP BY)
3 2 TABLE ACCESS (FULL) OF 'MYTABLE'
Regards,
Rob.
SELECT C1, C2, C3, Code FROM tablename
WHERE Code IN
(
SELECT Code FROM tablename
GROUP BY Code
HAVING count(Code) = 1
)
select C1, C2, C3, Code
from tablename T1
where not exists ( select T2.exclude
from tablename T2
where T2.Code = T1.Code
and T2.rowid <> T1.rowid
)
PS. Watch out for NULL values in the Code column