update tables based on rows in it and other table - sql

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>

Related

Store bitmap to appropriate column - Oracle

I have a table:
table1
id col val rec_pos
1 Test 1 10 1
1 Test 2 20 2
1 Test 3 30 3
1 Test 2 20 4
1 Empty 0101 5
1 Invalid 1011 6
2 Test 4 30 2
2 Test 5 30 3
2 Test 6 30 4
2 Test 5 30 5
2 Empty 11101 6
2 Invalid 10101 7
3 Test 7 30 5
3 Test 8 30 6
3 Test 8 30 7
3 Test 8 30 8
3 Empty 11110101 9
3 Invalid 10010101 10
4 Test 9 30 3
4 Empty 1101 5
4 Invalid 1011 6
For each unique id, I need to grab val for col = 'Empty' and then using rec_pos, add a new column called empty and add the appropriate values.
Same for invalid, for each unique id, I need to grab val for col = 'Invalid' and then using rec_pos, add a new column called invalid and add the appropriate values.
Example:
For id = 1, col = Empty, val = 0101
rec_pos = 1, add value in empty column = 0
rec_pos = 2, add value in empty column = 1
rec_pos = 3, add value in empty column = 0
rec_pos = 4, add value in empty column = 1
For id = 4, col = Empty, val = 1101
rec_pos = 1, add value in empty column = 1
rec_pos = 2, add value in empty column = 1
rec_pos = 3, add value in empty column = 0
rec_pos = 4, add value in empty column = 1
Output would be:
id col val rec_pos empty invalid
1 Test 1 10 1 0 1
1 Test 2 20 2 1 0
1 Test 3 30 3 0 1
1 Test 2 20 4 1 1
1 Empty 0101 5 0 0
1 Invalid 1011 6 0 0
2 Test 4 30 2 1 0
2 Test 5 30 3 1 1
2 Test 6 30 4 0 0
2 Test 5 30 5 1 1
2 Empty 11101 6 0 0
2 Invalid 10101 7 0 0
3 Test 7 30 5 0 0
3 Test 8 30 6 1 1
3 Test 8 30 7 0 0
3 Test 8 30 8 1 1
3 Empty 11110101 9 0 0
3 Invalid 10010101 10 0 0
4 Test 9 30 3 0 1
4 Empty 1101 5 0 0
4 Invalid 1011 6 0 0
How can I read the values and then appropriately assign it to respective rec_pos for the same id?
If position is determined by rec_pos then you can use simply susbtr combined with analytical max:
select t.*,
nvl(substr(max(case col when 'Empty' then val end)
over (partition by id), rec_pos, 1), 0) empty,
nvl(substr(max(case col when 'Invalid' then val end)
over (partition by id), rec_pos, 1), 0) invalid
from table1 t
or with correlated subqueries:
select t.*,
nvl(substr((select val
from table1 e
where e.id = t.id and col= 'Empty'), rec_pos, 1), 0) empty,
nvl(substr((select val
from table1 i
where i.id = t.id and col= 'Invalid'), rec_pos, 1), 0) invalid
from table1 t
dbfiddle demo
If empty and invald are real columns in your table then use simple merge with any of the above queries to update them. But it's better to make view when a column results from calculations from others.
Test case (only for IDs 1 and 4; didn't feel like typing that much):
SQL> create table test
2 (id number,
3 col varchar2(10),
4 val varchar2(10),
5 rec_pos number,
6 empty number,
7 invalid number);
Table created.
SQL> insert into test (id, col, val, rec_pos)
2 (select 1, 'test 1', '10' , 1 from dual union all
3 select 1, 'test 2' , '20' , 2 from dual union all
4 select 1, 'test 3' , '30' , 3 from dual union all
5 select 1, 'test 2' , '20' , 4 from dual union all
6 select 1, 'empty' , '0101', 5 from dual union all
7 select 1, 'invalid', '1011', 6 from dual union all
8 --
9 select 4, 'test 9' , '30' , 3 from dual union all
10 select 4, 'empty' , '1101', 5 from dual union all
11 select 4, 'invalid', '1011', 6 from dual
12 );
9 rows created.
SQL> select * From test;
ID COL VAL REC_POS EMPTY INVALID
---------- ---------- ---------- ---------- ---------- ----------
1 test 1 10 1
1 test 2 20 2
1 test 3 30 3
1 test 2 20 4
1 empty 0101 5
1 invalid 1011 6
4 test 9 30 3
4 empty 1101 5
4 invalid 1011 6
9 rows selected.
SQL>
Update statement:
SQL> update test e set
2 e.empty = (select nvl(x.digit, 0)
3 from ( select t.id,
4 substr(t.val, column_value, 1) digit,
5 column_value rec_pos
6 from test t join
7 table(cast(multiset(select level from dual
8 connect by level <= (select max(t1.rec_pos)
9 from test t1
10 where t1.id = t.id
11 )
12 ) as sys.odcinumberlist ))
13 on 1 = 1
14 where t.col = 'empty'
15 ) x
16 where x.id = e.id
17 and x.rec_pos = e.rec_pos
18 ),
19 --
20 e.invalid = (select nvl(x.digit, 0)
21 from ( select t.id,
22 substr(t.val, column_value, 1) digit,
23 column_value rec_pos
24 from test t join
25 table(cast(multiset(select level from dual
26 connect by level <= (select max(t1.rec_pos)
27 from test t1
28 where t1.id = t.id
29 )
30 ) as sys.odcinumberlist ))
31 on 1 = 1
32 where t.col = 'invalid'
33 ) x
34 where x.id = e.id
35 and x.rec_pos = e.rec_pos
36 );
9 rows updated.
SQL>
What does it do?
takes VAL and splits it into rows
position (for SUBSTR) is determined by the maximum REC_POS for that ID, so that you could use NVL later on, while updating EMPTY (or INVALID) column
basically, both updates are equal, they differ only in what you're updating (lines #14 and #32)
Result:
SQL> select * from test;
ID COL VAL REC_POS EMPTY INVALID
---------- ---------- ---------- ---------- ---------- ----------
1 test 1 10 1 0 1
1 test 2 20 2 1 0
1 test 3 30 3 0 1
1 test 2 20 4 1 1
1 empty 0101 5 0 0
1 invalid 1011 6 0 0
4 test 9 30 3 0 1
4 empty 1101 5 0 0
4 invalid 1011 6 0 0
9 rows selected.
SQL>
I think that this gives you the output that you asked for.
SELECT t.id,
t.col,
t.val,
t.rec_pos,
NVL(e.empty, 0) AS empty,
NVL(i.invalid, 0) AS invalid
FROM
table1 t
LEFT
JOIN (SELECT DISTINCT t.id, levels.column_value AS rec_pos, SUBSTR(val, levels.column_value, 1) AS empty
FROM table1 t, TABLE(CAST(MULTISET(SELECT level FROM dual CONNECT BY level <= LENGTH(val)) AS sys.OdciNumberList)) levels
WHERE t.col = 'Empty' ORDER BY id) e ON e.id = t.id AND e.rec_pos = t.rec_pos
LEFT
JOIN (SELECT DISTINCT t.id, levels.column_value AS rec_pos, SUBSTR(val, levels.column_value, 1) AS invalid
FROM table1 t, TABLE(CAST(MULTISET(SELECT level FROM dual CONNECT BY level <= LENGTH(val)) AS sys.OdciNumberList)) levels
WHERE t.col = 'Invalid' ORDER BY id) i ON i.id = t.id AND i.rec_pos = t.rec_pos
ORDER
BY t.id, t.rec_pos;

find the difference between 2 rows

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

Select all rows from table A and in the same set of results more than one column from table B

I have two tables in SQL Server 2012, and I need to get more than one column from one of them using some wheres, but I can get the result I want =S :
This are my two tables:
Table A:
id name
--------------
1 AAA
2 BBB
3 CCC
4 DDD
5 EEE
6 FFF
7 GGG
Table B:
idB id(A) price
----------------------
0 1 50
0 2 60
0 3 70
0 4 80
0 5 90
1 1 110
1 2 120
1 6 160
3 2 220
3 3 230
3 4 240
3 5 250
3 6 260
And I need a query that shows this result from this tables:
A.id A.name B.Price(idB=0) B.Price(idB=1) B.Price(idB=3)
-------------------------------------------------------------------
1 AAA 50 110 NULL
2 BBB 60 120 220
3 CCC 70 NULL 230
4 DDD 80 NULL 240
5 EEE 90 NULL 250
6 FFF NULL 160 260
Any idea how I can get this result?
I appreciate any help
Saludos
Do the inner join and use conditional aggravation
select a.id, a.name,
max(case when b.idB = 0 then b.price end) as [B.Price(idB=0)],
max(case when b.idB = 1 then b.price end) as [B.Price(idB=1)],
max(case when b.idB = 3 then b.price end) as [B.Price(idB=3)]
from tableA a
inner join tableB b on b.[id(A)] = a.id
group by a.id, a.name;
I hope this will work for you
DECLARE #a TABLE(A1 INT, A2 NVARCHAR(10))
INSERT #a VALUES
(1 ,'AAA')
,(2 ,'BBB')
,(3 ,'CCC')
,(4 ,'DDD')
,(5 ,'EEE')
,(6 ,'FFF')
,(7 ,'GGG')
DECLARE #b TABLE (B1 INT, B2 INT, B3 INT)
INSERT #b VALUES
(0, 1, 50 )
,(0, 2, 60 )
,(0, 3, 70 )
,(0, 4, 80 )
,(0, 5, 90 )
,(1, 1, 110)
,(1, 2, 120)
,(1, 6, 160)
,(3, 2, 220)
,(3, 3, 230)
,(3, 4, 240)
,(3, 5, 250)
,(3, 6, 260)
SELECT a.A1 [A.id], a.A2 [A.name], b.B3 [B.Price(idB=0)], b1.B3 [B.Price(idB=1)], b2.B3[B.Price(idB=3)] FROM #a a
LEFT JOIN #b b ON a.A1 = b.B2 AND b.B1 = 0
LEFT JOIN #b b1 ON a.A1 = b1.B2 AND b1.B1 = 1
LEFT JOIN #b b2 ON a.A1 =b2. B2 AND b2.B1 = 3
-------------------------------------------------------------
--Result
-------------------------------------------------------------
A.id A.name B.Price(idB=0) B.Price(idB=1) B.Price(idB=3)
1 AAA 50 110 NULL
2 BBB 60 120 220
3 CCC 70 NULL 230
4 DDD 80 NULL 240
5 EEE 90 NULL 250
6 FFF NULL 160 260
7 GGG NULL NULL NULL
Please use like this-(Change column name accordingly)
SELECT a.*,b1.price,b2.price,b3.price FROM TableA a
LEFT JOIN TableB b1 ON a.id = b1.idA AND b1.idB = 0
LEFT JOIN TableB b2 ON a.id = b2.idA AND b2.idB = 1
LEFT JOIN TableB b3 ON a.id = b3.idA AND b3.idB = 3
WHERE b1.price IS NOT NULL or b2.price IS NOT NULL or b3.price IS NOT NULL
OUTPUT
id name price price price
----------- ---------- ----------- ----------- -----------
1 AAA 50 110 NULL
2 BBB 60 120 220
3 CCC 70 NULL 230
4 DDD 80 NULL 240
5 EEE 90 NULL 250
6 FFF NULL 160 260
(6 rows affected)

Joining the tables.Aggregating and consolidating the counts

enter image description hereI have two tables
Table 1-qualified players
Id_sequence
121
345
765
Table 2 - All enteries related to players Note :there are only 6 game_ids 1a,1b,1c,2a,2b,2c
id_sequence player_id game_id phone_no
121 aaa 1a 111111111
131 aaa 1b 111222111
141 aaa 1a 111112222
345 bbb 2a 222222222
656 bbb 2c 222211122
789 bbb 1c 222211122
632 bbb 2b 222222222
765 ccc 2b 333333333
897 ddd 1a 444444444
433 ddd 2c 555555444
Expected Output:
select all id_sequence from Table 1 and join Table 2.
Then select all other data related to that player_id then aggregate and consolidate the counts
player_id game id_1a game id_1b game id_1c game id_2a game id_2b game id_2c no_of _phones
aaa 2 1 3
bbb 1 1 1 1 2
ccc 1 1
Currently,I am creating a table 3 that stores the player_id obtained from joining table 1 and table 2 .Then again joining table 3 and 2.
Any thoughts and ideas will greatly help.
Test data (see also: dbfiddle)
SQL> select * from ae;
ID_SEQUENCE PLAYER_ID GAME_ID PHONE_NO
121 aaa 1a 111111111
131 aaa 1b 111222111
141 aaa 1a 111112222
345 bbb 2a 222222222
656 bbb 2c 222211122
789 bbb 1c 222211122
632 bbb 2b 222222222
765 ccc 2b 333333333
897 ddd 1a 444444444
433 ddd 2c 555555444
Query
select
dt1.*
, dt2.no_of_phones
from (
(
select game_id, player_id
from ae
) pivot
(
count( game_id ) for game_id in
(
'1a' as "game id_1a"
, '1b' as "game id_1b"
, '1c' as "game id_1c"
, '2a' as "game id_2a"
, '2b' as "game id_2b"
, '2c' as "game id_2c"
)
)
) dt1 join (
select
player_id
, count( phone_no ) no_of_phones
from ae
group by player_id
) dt2
on dt1.player_id = dt2.player_id
order by dt1.player_id
;
Result
PLAYER_ID game id_1a game id_1b game id_1c game id_2a game id_2b game id_2c NO_OF_PHONES
aaa 2 1 0 0 0 0 3
bbb 0 0 1 1 1 1 4
ccc 0 0 0 0 1 0 1
ddd 1 0 0 0 0 1 2
A PIVOT should take care of it
SQL> create table t1 ( id int);
Table created.
SQL>
SQL> insert into t1 values (121 );
1 row created.
SQL> insert into t1 values (345 );
1 row created.
SQL> insert into t1 values (765 );
1 row created.
SQL>
SQL>
SQL> create table t2 ( id int, player varchar2(10), game varchar2(10), phone int );
Table created.
SQL>
SQL> insert into t2 values (121 ,'aaa' , '1a' , 111111111);
1 row created.
SQL> insert into t2 values (131 ,'aaa' , '1b' , 111222111 );
1 row created.
SQL> insert into t2 values (141 ,'aaa' , '1a' , 111112222 );
1 row created.
SQL> insert into t2 values (345 ,'bbb' , '2a' , 222222222 );
1 row created.
SQL> insert into t2 values (656 ,'bbb' , '2c' , 222211122 );
1 row created.
SQL> insert into t2 values (789 ,'bbb' , '1c' , 222211122 );
1 row created.
SQL> insert into t2 values (632 ,'bbb' , '2b' , 222222222 );
1 row created.
SQL> insert into t2 values (765 ,'ccc' , '2b' , 333333333 );
1 row created.
SQL> insert into t2 values (897 ,'ddd' , '1a' , 444444444 );
1 row created.
SQL> insert into t2 values (433 ,'ddd' , '2c' , 555555444);
1 row created.
SQL>
SQL>
SQL> SELECT *
2 FROM (SELECT player, game, phone
3 FROM t2)
4 PIVOT (count(phone) AS cnt FOR (game) IN ('1a','1b','2a','2b','3a','3c'));
PLAYER '1a'_CNT '1b'_CNT '2a'_CNT '2b'_CNT '3a'_CNT '3c'_CNT
---------- ---------- ---------- ---------- ---------- ---------- ----------
aaa 2 1 0 0 0 0
bbb 0 0 1 1 0 0
ddd 1 0 0 0 0 0
ccc 0 0 0 1 0 0
4 rows selected.
Addenda to get NO_PHONES
SQL> SELECT *
2 FROM (SELECT player, game, phone, count( distinct phone) over ( partition by player ) as no_phones
3 FROM t2)
4 PIVOT (count(phone) AS cnt FOR (game) IN ('1a','1b','2a','2b','3a','3c'));
PLAYER NO_PHONES '1a'_CNT '1b'_CNT '2a'_CNT '2b'_CNT '3a'_CNT '3c'_CNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ccc 1 0 0 0 1 0 0
ddd 2 1 0 0 0 0 0
aaa 3 2 1 0 0 0 0
bbb 2 0 0 1 1 0 0

SQL pad query result for missing groups

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