I was trying to insert only distinct records from source table to destination table using Merge command in Vertica. I had tried the same thing in SQL using subquery but in vertica its not allowing.
following is the error:
[Vertica][VJDBC](5665) ERROR: Subquery in MERGE is not supported
please help me with this.
Thanks in advance
It was not possible to use Subquery in vertica merge.
MERGE INTO Target TGT
USING (Select distinct * from Sources) as SRC
ON TGT.CD = SRC.CD
I created a view for :
Select distinct * from Sources
used it like this:
MERGE INTO Target TGT
USING SRC_VW as SRC
ON TGT.CD = SRC.CD
it solved the purpose. Just thought of posting it for future use only.
Do you need to perform a MERGE operation with big data volumes?
Then, you should consider enabling an optimized MERGE plan instead of a standard MERGE, which is considerably faster.
Should you be interested, shout, and I'll explain you the details as yet another answer here.
Happy playing
Marco the Sane
Optimized MERGE possibility.
I'm basing it on a mutilated Slowly Changing Dimension table. It brings the idea across, but don't take it as a design blueprint for anything in reality ....!
Let’s say you have, among other rows, these in your target table. cust_key is the surrogate primary key, and the combination of cust_id and cust_to_dt is the other unique identifier of the table:
cust_key|cust_id|cust_to_dt|cust_first_name |cust_last_name |cust_phoneno |cust_loyalty_lvl|cust_org_id
1| 7|9999-12-31|Lionel |Prosser |+41(0)79 387 31 07| 1| 0
2| 14|9999-12-31|Hotblack |Desiato |+41(0)79 387 31 14| 2| 0
3| 21|9999-12-31|Slartibartfast |Slartibartfast |+41(0)79 387 31 21| 3| 0
4| 28|9999-12-31|Pizpot |Gargravarr |+41(0)79 387 31 28| 4| 0
5| 35|9999-12-31|Know-Nothing-Bozo|the Non-Wonder Dog|+41(0)79 387 31 35| 5| 0
6| 42|9999-12-31|Fook |Fook |+41(0)79 387 31 42| 6| 0
The definition of the target table would be this:
-- create a stand-alone sequence
CREATE SEQUENCE source_seq;
-- the target's surrogate key defaults to its sequence's NEXTVAL ….
CREATE TABLE target (
cust_key BIGINT DEFAULT target_seq.NEXTVAL NOT NULL
, cust_id BIGINT
, cust_to_dt DATE
, cust_first_name NCHAR VARYING(30)
, cust_last_name NCHAR VARYING(30)
, cust_phoneno NCHAR VARYING(30)
, cust_loyalty_lvl BIGINT
, cust_org_id BIGINT
, PRIMARY KEY(cust_key)
)
UNSEGMENTED ALL NODES;
Your source table – without the surrogate key value for starters – looks like this. 6 rows are updates of existing ones, and 1 new row, Thor with cust_id 43.:
cust_id|cust_to_dt|cust_first_name |cust_last_name |cust_phoneno |cust_loyalty_lvl|cust_org_id
7|9999-12-31|Lionel |Prosser |+41(0)79 387 31 07| 2| 0
14|9999-12-31|Hotblack |Desiato |+41(0)79 387 31 14| 3| 0
21|9999-12-31|Slartibartfast |Slartibartfast |+41(0)79 387 31 21| 4| 0
28|9999-12-31|Pizpot |Gargravarr |+41(0)79 387 31 28| 5| 0
35|9999-12-31|Know-Nothing-Bozo|the Non-Wonder Dog|+41(0)79 387 31 35| 6| 0
42|9999-12-31|Fook |Fook |+41(0)79 387 31 42| 7| 0
43|9999-12-31|Thor |Thor |+41(0)79 623 84 75| 6| 1
Your MERGE source table is built like the target table.:
CREATE TABLE merge_src LIKE target INCLUDING PROJECTIONS;
You fill it from the delta table so that you pick the existing surrogate keys from the target, and where they don’t exist, you use target_seq.NEXTVAL to get a new surrogate key. In order to do that, you left join your source to your target using the the combination of cust_id and cust_to_dt, the other possibility to uniquely identify the target rows:
INSERT /*+ DIRECT */ INTO merge_src
SELECT
IFNULL(tgt.cust_key,target_seq.NEXTVAL) AS cust_key
, src.cust_id
, src.cust_to_dt
, src.cust_first_name
, src.cust_last_name
, src.cust_phoneno
, src.cust_loyalty_lvl
, src.cust_org_id
FROM source src
LEFT
JOIN target tgt
USING(cust_id,cust_to_dt)
;
Your merge source table now looks like this – the new row with cust_id 43, Thor, gets a new surrogate key:
SQL>select * from merge_src;
cust_key|cust_id|cust_to_dt|cust_first_name |cust_last_name |cust_phoneno |cust_loyalty_lvl|cust_org_id
1| 7|9999-12-31|Lionel |Prosser |+41(0)79 387 31 07| 2| 0
2| 14|9999-12-31|Hotblack |Desiato |+41(0)79 387 31 14| 3| 0
3| 21|9999-12-31|Slartibartfast |Slartibartfast |+41(0)79 387 31 21| 4| 0
4| 28|9999-12-31|Pizpot |Gargravarr |+41(0)79 387 31 28| 5| 0
5| 35|9999-12-31|Know-Nothing-Bozo|the Non-Wonder Dog|+41(0)79 387 31 35| 6| 0
6| 42|9999-12-31|Fook |Fook |+41(0)79 387 31 42| 7| 0
250,007| 43|9999-12-31|Thor |Thor |+41(0)79 623 84 75| 6| 1
The MERGE between merge_src and target uses an optimized MERGE, using the surrogate key in the ON clause (I just replaced the code for the digraph objects for the GraphViz format by [...] placeholders). Look especially at the Access Path for the DELETE – it has a MERGEJOIN (inputs presorted) and uses Side Information Passing (SIP1):
SQL>EXPLAIN
...>MERGE /*+DIRECT*/
...>INTO target t
...>USING merge_src s
...> ON s.cust_key = t.cust_key
...>WHEN MATCHED THEN UPDATE SET
...> cust_key = s.cust_key
...>, cust_id = s.cust_id
...>, cust_to_dt = s.cust_to_dt
...>, cust_first_name = s.cust_first_name
...>, cust_last_name = s.cust_last_name
...>, cust_phoneno = s.cust_phoneno
...>, cust_loyalty_lvl = s.cust_loyalty_lvl
...>, cust_org_id = s.cust_org_id
...>WHEN NOT MATCHED THEN INSERT (
...> cust_key
...>, cust_id
...>, cust_to_dt
...>, cust_first_name
...>, cust_last_name
...>, cust_phoneno
...>, cust_loyalty_lvl
...>, cust_org_id
...>) VALUES (
...> s.cust_key
...>, s.cust_id
...>, s.cust_to_dt
...>, s.cust_first_name
...>, s.cust_last_name
...>, s.cust_phoneno
...>, s.cust_loyalty_lvl
...>, s.cust_org_id
...>);
QUERY PLAN
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN MERGE /*+DIRECT*/ INTO target t USING merge_src s ON s.cust_key = t.cust_key WHEN MATCHED THEN UPDATE SET cust_key = s.cust_key , cust_id = s.cust_id , cust_to_dt = s.cust_to_dt , cust_first_name = s.cust_first_name , cust_last_name = s.cust_last_name , cust_phoneno = s.cust_phoneno , cust_loyalty_lvl = s.cust_loyalty_lvl , cust_org_id = s.cust_org_id WHEN NOT MATCHED THEN INSERT ( cust_key , cust_id , cust_to_dt , cust_first_name , cust_last_name , cust_phoneno , cust_loyalty_lvl , cust_org_id ) VALUES ( s.cust_key , s.cust_id , s.cust_to_dt , s.cust_first_name , s.cust_last_name , s.cust_phoneno , s.cust_loyalty_lvl , s.cust_org_id )
Access Path:
+-DML INSERT [Cost: 0, Rows: 0]
| Target Projection: scd.target_super
| Target Prep:
| +---> STORAGE ACCESS for s [Cost: 40, Rows: 7 (NO STATISTICS)] (PATH ID: 3)
| | Projection: scd.merge_src_super
| | Materialize: s.cust_key, s.cust_id, s.cust_to_dt, s.cust_first_name, s.cust_last_name, s.cust_phoneno, s.cust_loyalty_lvl, s.cust_org_id
[...]
Lock Map - Table (Mode)
----------------------------------------------
target(I)
----------------------------------------------
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN MERGE /*+DIRECT*/ INTO target t USING merge_src s ON s.cust_key = t.cust_key WHEN MATCHED THEN UPDATE SET cust_key = s.cust_key , cust_id = s.cust_id , cust_to_dt = s.cust_to_dt , cust_first_name = s.cust_first_name , cust_last_name = s.cust_last_name , cust_phoneno = s.cust_phoneno , cust_loyalty_lvl = s.cust_loyalty_lvl , cust_org_id = s.cust_org_id WHEN NOT MATCHED THEN INSERT ( cust_key , cust_id , cust_to_dt , cust_first_name , cust_last_name , cust_phoneno , cust_loyalty_lvl , cust_org_id ) VALUES ( s.cust_key , s.cust_id , s.cust_to_dt , s.cust_first_name , s.cust_last_name , s.cust_phoneno , s.cust_loyalty_lvl , s.cust_org_id )
Access Path:
+-DML DELETE [Cost: 0, Rows: 0]
| Target Projection: scd.target_super (DELETE ON CONTAINER)
| Target Prep:
| +---> JOIN MERGEJOIN(inputs presorted) [Semi] [Cost: 11, Rows: 7 (NO STATISTICS)] (PATH ID: 1)
| | Join Cond: (VAL(2) = t.cust_key)
| | +-- Outer -> STORAGE ACCESS for t [Cost: 5, Rows: 6 (NO STATISTICS)] (PATH ID: 2)
| | | Projection: scd.target_super
| | | Materialize: t.cust_key
| | | Runtime Filter: (SIP1(MergeJoin): t.cust_key)
| | +-- Inner -> SELECT [Cost: 5, Rows: 7 (NO STATISTICS)] (PATH ID: 3)
| | | +---> STORAGE ACCESS for s [Cost: 5, Rows: 7 (NO STATISTICS)] (PATH ID: 4)
| | | | Projection: scd.merge_src_super
| | | | Materialize: s.cust_key
Lock Map - Table (Mode)
----------------------------------------------
target(X)
----------------------------------------------
Hope all this makes some sense…
Happy playing -
Marco the Sane
Related
having sql for a big table join (232mln records) with GTT by index. explanation looks like below:
4 NESTED LOOPS
( Estim. Costs = 439,300 , Estim. #Rows = 548,275 )
Estim. CPU-Costs = 3,642,574,678 Estim. IO-Costs = 438,956
1 INDEX FAST FULL SCAN ZTRM_REXP_PRESEL~0
( Estim. Costs = 336 , Estim. #Rows = 548,275 )
Estim. CPU-Costs = 3,432,714 Estim. IO-Costs = 336
3 TABLE ACCESS BY INDEX ROWID BATCHED TEXT_REXP_ITEM
( Estim. Costs = 1 , Estim. #Rows = 1 )
Estim. CPU-Costs = 6,637 Estim. IO-Costs = 1
Filter Predicates
2 INDEX RANGE SCAN TEXT_REXP_ITEM~Y01
( Estim. Costs = 1 , Estim. #Rows = 1 )
Search Columns: 3
Estim. CPU-Costs = 4,523 Estim. IO-Costs = 1
Access Predicates
it shows wrong estimations because of GTT usage. the goal is to make Nested loop for index (2) and gtt (1) first and only then make access to a table itself (3). for some reason, hint USE_NL_WITH_INDEX("TEXT_REXP_ITEM" "TEXT_REXP_ITEM~Y01") is simply being ignored. any ideas why?
(1) consists of
EXPOSURE_ID
VERSION
(2) consists of
Column Name #Distinct
MANDT 1
ZZHEAD_EXPOSURE_ID 251,454
ZZHEAD_VERSION 3,217
ZZHEAD_ATTRIBUTE_DH01 1,691
EXT_ITEM_ID 823
ZZHEAD_ATTRIBUTE_LH01 3
ZZHEAD_RELEASE_STATE 1
(1) and (2) are joined by exposure_id and version fields
text explanation
| 3 | NESTED LOOPS | | 548K| 135M| 439K (1)| 00:00:18 |
| 4 | INDEX FAST FULL SCAN | ZTRM_REXP_PRESEL~0 | 548K| 16M| 336 (0)| 00:00:01 |
|* 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TEXT_REXP_ITEM | 1 | 228 | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | TEXT_REXP_ITEM~Y01 | 1 | | 1 (0)| 00:00:01 |
thank you
The optimizer is obeying the hint. As the docs say:
The USE_NL_WITH_INDEX hint instructs the optimizer to join the
specified table to another row source with a nested loops join using
the specified table as the inner table
In a nested loop, the outer table is the first one accessed. The inner table is the second.
So the plan uses ZTRM_REXP_PRESEL~0 as the outer table. And TEXT_REXP_ITEM as the inner table. Which is exactly what you've asked for!
Constructing a similar example and using Oracle Database 19c's hint reporting mechanism shows the hint is followed:
create table t1 (
c1 int
);
create table t2 (
c1 int, c2 varchar2(100)
);
create index i1
on t1 ( c1 );
create index i2
on t2 ( c1 );
insert into t1 values ( 1, 'stuff' );
insert into t2
with rws as (
select level x from dual
connect by level <= 1000
)
select x, rpad ( 'stuff', 100, 'f' )
from rws;
exec dbms_stats.gather_table_stats ( user, 't1' ) ;
exec dbms_stats.gather_table_stats ( user, 't2' ) ;
set serveroutput off
select /*+ USE_NL_WITH_INDEX ( T2 I2 ) */*
from t1
join t2
on t1.c1 = t2.c1;
select *
from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +HINT_REPORT'));
Plan hash value: 3271411982
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | NESTED LOOPS | |
| 3 | INDEX FULL SCAN | I1 |
| 4 | INDEX RANGE SCAN | I2 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 |
---------------------------------------------
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1
---------------------------------------------------------------------------
4 - SEL$58A6D7F6 / T2#SEL$1
- USE_NL_WITH_INDEX ( T2 I2 )
Select * from testtable;
You can see that there are duplicate rows when we only consider 4 columns.
Can we simply make it one row and split two attribute values(mobile numebr & values(OM or OD only)) as two separate columns so that duplicates are removed like below?
create table testtable
(
ACCOUNT_NUM VARCHAR2(30),
OTC_ID NUMBER(9),
OTC_SEQ NUMBER(9),
OTC_MNY NUMBER(9),
ATTRIBUTE_VALUE VARCHAR2(30)
);
insert into TESTTABLE (ACCOUNT_NUM, OTC_ID, OTC_SEQ, OTC_MNY, ATTRIBUTE_VALUE)
values ('0000000191', 381, 1, 1000, 'OM');
insert into TESTTABLE (ACCOUNT_NUM, OTC_ID, OTC_SEQ, OTC_MNY, ATTRIBUTE_VALUE)
values ('0000000191', 381, 1, 1000, '07400004483');
insert into TESTTABLE (ACCOUNT_NUM, OTC_ID, OTC_SEQ, OTC_MNY, ATTRIBUTE_VALUE)
values ('0000000191', 382, 2, 1000, 'OD');
insert into TESTTABLE (ACCOUNT_NUM, OTC_ID, OTC_SEQ, OTC_MNY, ATTRIBUTE_VALUE)
values ('0000000191', 382, 2, 1000, '07400004483');
insert into TESTTABLE (ACCOUNT_NUM, OTC_ID, OTC_SEQ, OTC_MNY, ATTRIBUTE_VALUE)
values ('0000000191', 397, 3, 3000, 'OD');
insert into TESTTABLE (ACCOUNT_NUM, OTC_ID, OTC_SEQ, OTC_MNY, ATTRIBUTE_VALUE)
values ('0000000191', 397, 3, 3000, '07800000688');
You want to separate OM/OD values from others. One option is to use conditional aggregation:
select
account_num,
otc_id,
otc_seq,
otc_mny,
max(case when attribute_value in ('OM', 'OD') then attribute_value end)
as attribute_value_1,
max(case when attribute_value not in ('OM', 'OD') then attribute_value end)
as attribute_value_2
from testtable
group by account_num, otc_id, otc_seq, otc_mny
order by account_num, otc_id, otc_seq, otc_mny
Demo on DB Fiddle:
ACCOUNT_NUM | OTC_ID | OTC_SEQ | OTC_MNY | ATTRIBUTE_VALUE_1 | ATTRIBUTE_VALUE_2
:---------- | -----: | ------: | ------: | :---------------- | :----------------
0000000191 | 381 | 1 | 1000 | OM | 07400004483
0000000191 | 382 | 2 | 1000 | OD | 07400004483
0000000191 | 397 | 3 | 3000 | OD | 07800000688
I have table with following records;
ID | NN | MBL | IC | OTHER
---+-----+------+----+------
1 | 123 | | | ac
2 | | 544 | | dc
3 | | | 524| df
4 |527 | | 124| ff
5 |123 | | | tr // duplicate NN of ID 1
6 | | 544 | | op // duplicate MBL of ID 2
7 | | | 124| ii // duplicate for IC ID 4
When querying with select I need just records with single entry, skipping second occurrence,
select
ID, NN, MBL, IC, OTHER
from
TABLE1 // this should return only one entry of any NN, MBL and IC
How do I get this, I cannot use distinct for multiple columns and I also need ID and OTHER column to display in select query
Expecting result like this:
1 | 123 | | | ac
2 | | 544 | | dc
3 | | | 524| df
4 |527 | | 124| ff
You can use the analytical function ROW_NUMBER() to calculate ranks over each column you want and filter only these rows with rank = 1.
Here is an example:
WITH testdata AS (
SELECT 1 AS ID, 123 AS NN, NULL AS MBL, NULL AS IC, 'ac' AS OTHER FROM DUAL UNION ALL
SELECT 2, NULL, 544 , NULL, 'dc' FROM DUAL UNION ALL
SELECT 3, NULL, NULL, 524 , 'df' FROM DUAL UNION ALL
SELECT 4, 527, NULL, 124, 'ff' FROM DUAL UNION ALL
SELECT 5, 123, NULL, NULL, 'tr' FROM DUAL UNION ALL
SELECT 6, NULL, 544, NULL, 'op' FROM DUAL UNION ALL
SELECT 7, NULL, NULL , 124, 'ii' FROM DUAL
)
SELECT *
FROM(SELECT ID,
NN,
CASE WHEN NN IS NULL THEN 1 ELSE ROW_NUMBER() OVER (PARTITION BY NN ORDER BY ID) END AS NN_RANG,
MBL,
CASE WHEN MBL IS NULL THEN 1 ELSE ROW_NUMBER() OVER (PARTITION BY MBL ORDER BY ID) END AS MBL_RANG,
IC,
CASE WHEN IC IS NULL THEN 1 ELSE ROW_NUMBER() OVER (PARTITION BY IC ORDER BY ID) END AS IC_RANG,
OTHER
FROM testdata
)
WHERE NN_RANG = 1
AND MBL_RANG = 1
AND IC_RANG = 1
;
Hope it helps.
I'm trying to join two tables with LEFT JOIN in Oracle. I need to include only the first record from the "right" joined table.
See the example below:
Table A
code | emp_no
101 | 11111
102 | 22222
103 | 33333
104 | 44444
105 | 55555
Table B
code | city | county
101 | City1 | Country1
101 | City2 | Country1
101 | City3 | Country1
102 | City4 | Country2
103 | City5 | Country3
Expected Output:
code | emp_no | city | county
101 | 11111 | City1 | Country1
102 | 22222 | City4 | Country2
103 | 33333 | City5 | Country3
104 | 44444 | NULL | NULL
105 | 55555 | NULL | NULL
I need to pick the first matched record from table B and ignore all other rows.
The query above suppose to works:
SELECT *
FROM TABLE_A a
LEFT JOIN TABLE_B b ON b.CODE = a.CODE
AND b.CODE =
(
SELECT CODE
FROM TABLE_B
WHERE ROWNUM = 1
)
But I'm getting the error:
ORA-01799: a column may not be outer-joined to a subquery
How can I do this?
Thanks
On Oracle 12c you can use OUTER APPLY and FETCH FIRST clauses:
SELECT *
FROM tableA a
OUTER APPLY (
SELECT * FROM tableB b
WHERE a.code = b.code
ORDER BY city, county
FETCH FIRST ROW ONLY
)
CODE EMP_NO CODE CITY COUNTY
---------- ---------- ---------- ----- --------
101 11111 101 City1 Country1
102 22222 102 City4 Country2
103 33333 103 City5 Country3
104 44444
105 55555
You can use the min() aggrenate function with the keep (dense_rank first ...) syntax to get the 'first' matching data from the outer-joined table:
select a.code, a.emp_no,
min(b.city) keep (dense_rank first order by city, county) as city,
min(b.county) keep (dense_rank first order by city, county) as county
from table_a a
left join table_b b on b.code = a.code
group by a.code, a.emp_no
order by a.code, a.emp_no;
CODE EMP_NO CITY COUNTY
---------- ---------- ----- --------
101 11111 City1 Country1
102 22222 City4 Country2
103 33333 City5 Country3
104 44444
105 55555
You have to define what 'first' means though - I've gone with order by city, county inside the keep clause, but you may have another column you haven't shown that should dictate the order.
(You can order by null to make it somewhat arbitrary, but that's not generally a good idea, not least as running the same query later could give different results for the same data.)
using row_number() function and get records where row_number() = 1
SELECT select a.code,
a.emp_no,
b.city,
b.county
FROM table_a a
left join (SELECT code,
city,
county,
row_number()
over (
PARTITION BY code
ORDER BY city, county ) rn
FROM table_b) b
ON b.code = a.code
WHERE rn = 1 OR rn IS NULL;
Note: It is still unclear from the question what actually this means.
first record from the "right" joined table
I am having 2 tables by joining both i am getting some columns and values
Select
tbl_orderdetails.category_name,
tbl_orderdetails.branch_name,
tbl_ordermaster.created_date,
tbl_ordermaster.user_id,
tbl_orderdetails.order_details_id,
tbl_orderdetails.branch_id
From tbl_orderdetails Inner Join tbl_ordermaster ON
tbl_orderdetails.order_master_id=tbl_ordermaster.ordermasterid
where tbl_ordermaster.user_id='12'
I want to get number of times a particular branch name came.I used count but its not working and i want only max number of times the branch name came and top 3 to be displayed .
Eg:
vellore=100,
chennai=18,
tvl=80,
harithuwar=90
It should display only
vellore
harithwar
tvl
sample data
orderdetails
orderdatailsid | order_master_id |branchname| category| branchid
1 | 112 | vellore | nad | 123
2 | 112 | vellore | hu | 123
3 | 113 | chennai | ji | 121
4 | 112 | vellore | hi | 123
5 | 134 | tvl | ui | 145
6 | 134 | tvl | jo | 145
masterdetails
ordermasterid | userid
112 | 12
113 | 13
134 | 14
Try this
SELECT T.*,S.* FROM
(
Select TD.category_name,TD.branch_name,TM.created_date,TM.user_id,TD.order_details_id,TD.branch_id
From tbl_orderdetails TD Inner Join tbl_ordermaster TM ON
TD.order_master_id = TM.ordermasterid
Where TM.user_id='12'
) T Left Join
(
Select T1.branch_name,Count(T1.branch_name) As No_Of_Branch
From tbl_orderdetails T1 Inner Join tbl_ordermaster T2 ON
T1.order_master_id = T2.ordermasterid
Where T2.user_id='12'
Group By T1.branch_name
) S On S.branch_name = T.branch_name
Update
If you want to get Max of count
Try this
SELECT T.*,S.* FROM
(
Select TD.category_name,TD.branch_name,TM.created_date,TM.user_id,TD.order_details_id,TD.branch_id
From tbl_orderdetails TD Inner Join tbl_ordermaster TM ON
TD.order_master_id = TM.ordermasterid
Where TM.user_id='12'
) T Inner Join
(
SELECT M.branch_name,Max(M.No_Of_Branch) FROM
(
Select T1.branch_name,Count(T1.branch_name) As No_Of_Branch
From tbl_orderdetails T1 Inner Join tbl_ordermaster T2 ON
T1.order_master_id = T2.ordermasterid
Where T2.user_id='12'
Group By T1.branch_name
) M Group By M.branch_name
) S On S.branch_name = T.branch_name
Try this Count is working good below the Examples,
create table orderdetails(orderdatailsid number, order_master_id number,branchname varchar(20), category varchar(20), branchid number);
insert into orderdetails values (1 , 112 ,'vellore','nad', 123);
insert into orderdetails values (2 , 112 ,'vellore','hu', 123);
insert into orderdetails values (3 , 113 , 'chennai','ji', 121);
insert into orderdetails values (4 , 112 , 'vellore' ,'hi', 123);
insert into orderdetails values (5 , 134 , 'tvl','ui', 145);
insert into orderdetails values (6 , 134 , 'tvl','jo', 145);
insert into orderdetails values (7 , 113 , 'chennai','ji', 121);
insert into orderdetails values (8 , 112 , 'vellore','hi', 123);
insert into orderdetails values (9 , 134 , 'tvl','ui', 145);
select * from orderdetails;
create table masterdetails(ordermasterid number, userid number);
insert into masterdetails values(112 , 12);
insert into masterdetails values(113 , 13);
insert into masterdetails values(134 ,14);
select * from masterdetails;
SELECT * FROM (
SELECT orderdetails.branchname, count(*) as Cout
From orderdetails left Join masterdetails ON
orderdetails.order_master_id=masterdetails.ordermasterid
group by orderdetails.branchname
order by cout desc
) WHERE ROWNUM <4;