Outer Join Puzzle; Refactor Affects Results, Unexpectedly
Good afternoon. I have a complex query which is returning some unexpected results. Oddly, moving a specific join outside of the original query changes the results returned in a field from another table. This is a simplified version:
SELECT
A.PK,
A.Field1,
B.Field2,
C.Field3
FROM
A
INNER JOIN B ON A.PK = B.PK
LEFT JOIN C ON A.PK = C.PK
WHERE
A.Field = 'X'...running this query, I get 29 records but only one non-null value in C.Field3. If I then rewrite the query like this:
SELECT A.PK, A.Field1, B.Field2, A.Field3
FROM
SELECT
A.PK,
A.Field1,
C.Field3
FROM
A
LEFT JOIN C ON A.PK = C.PK
WHERE
A.Field = 'X'
) A
INNER JOIN B ON A.PK = B.PKSuddenly I get lots of values in Field3. I don't understand how this reorganization could affect the values returned. What am I missing?
The joins are all one-to-one, or to be exact one-to-zero-or-one.
Thank you,
Jonathan
Hi, Jonathan,
I don't see any obvious mistakes.
I suspect that when you simplified the question, you inadvertently removed the part that was causing the problem.
Post a little sample data (CREATE TABLE and INSERT statements for all tables, relevant columns only) that produces the strange results.
I suggest not using aliases that are the same as the names of tables in the same query. For example, since a is a table name, also using a as an alias for the in-line view that joins a and c is just inviting confusion. It's probably not causing your present problem, but why not call the sub-query by some unique name, like ac?
Similar Messages
-
Old outer join syntax produces different results from new syntax!
I have inherited a query that uses the old outer join syntax but that is yielding correct results. When I translate it to the new outer join syntax, I get the results I expect, but they are not correct! And I don't understand why the old syntax produces the results it produces. Bottom line: I want the results I'm getting from the old syntax, but I need it in the new syntax (I'm putting it into Reporting Services, and RS automatically converts old syntax to new).
Here's the query with the old outer join syntax that is working correctly:
Code Snippet
SELECT TE = COUNT(DISTINCT T1.ID),
UE = COUNT(DISTINCT T2.ID),
PE = CONVERT(MONEY, COUNT(DISTINCT T2.ID)) /
CONVERT(MONEY,COUNT(DISTINCT T1.ID))
FROM TABLE T1, TABLE T2
WHERE T1 *= T2
In this query, much to my surprise, TE <> UE and PE <> 1. However, TE, UE, and PE seem to be accurate!
Here's the query with the new outer join syntax that is working but not producing the results I need:
Code Snippet
SELECT TE = COUNT(DISTINCT T1.ID),
UE = COUNT(DISTINCT T2.ID),
PE = CONVERT(MONEY, COUNT(DISTINCT T2.ID)) /
CONVERT(MONEY,COUNT(DISTINCT T1.ID))
FROM TABLE T1 LEFT OUTER JOIN TABLE T2 ON T1.ID = T2.ID
Though not producing the results I need, it is producing what would be expected: TE = UE and PE = 1.
My questions:
1) Can someone who is familiar enough with the old syntax please help me understand why TE <> UE and PE <> 1 in the first query?
2) Can someone please tell me how to properly translate the first query to the new syntax so that it continues to produce the results in the first query?
Thank you very much.How can we reproduce the issue?
Code Snippet
USE [master]
GO
EXEC sp_dbcmptlevel Northwind, 80
GO
USE [Northwind]
GO
SELECT
TE
= COUNT(DISTINCT T1.OrderID),
UE = COUNT(DISTINCT T2.OrderID),
PE = CONVERT(MONEY, COUNT(DISTINCT T2.OrderID)) /
CONVERT(MONEY,COUNT(DISTINCT T1.OrderID))
FROM
dbo
.Orders T1, dbo.Orders T2
WHERE
T1
.OrderID *= T2.OrderID
SELECT
TE
= COUNT(DISTINCT T1.OrderID),
UE = COUNT(DISTINCT T2.OrderID),
PE = CONVERT(MONEY, COUNT(DISTINCT T2.OrderID)) /
CONVERT(MONEY,COUNT(DISTINCT T1.OrderID))
FROM
dbo
.Orders T1
LEFT OUTER JOIN
dbo.Orders T2
ON T1.OrderID = T2.OrderID
GO
EXEC sp_dbcmptlevel Northwind, 90
GO
Result:
TE
UE
PE
830
830
1.00
TE
UE
PE
830
830
1.00
As you can see, I am getting same results.
AMB -
Outer join that give no result
Hi everybody
Here are the scripts
CREATE TABLE dem_comment (
COMMENTID VARCHAR2(50 BYTE) NOT NULL,
PARENTID VARCHAR2(50 BYTE) NOT NULL,
DEM_DATE_CREATION_MEMO date)
CREATE TABLE demand(
NUM_PCE VARCHAR2(14 BYTE) NOT NULL,
NUM_DEMANDE VARCHAR2(8 BYTE)
insert into dem_comment VALUES (1,'12345ABCDEF',to_date('17/08/2012 10:18:34','DD/mm/YYyy HH:MI:SS'))
insert into demand values('12345','ABCDEF')
And the following is the request that have the problem
select dem.NUM_PCE, memo.parentid
from demand dem, dem_comment memo
where CONCAT(dem.NUM_PCE,dem.NUM_DEMANDE) = memo.parentId (+)
and memo.DEM_DATE_CREATION_MEMO = (select MAX(DEM_DATE_CREATION_MEMO)
FROM dem_comment memo
WHERE memo.parentId = CONCAT(dem.NUM_PCE,dem.NUM_DEMANDE))
And the result is the one i m waiting for
NUMPCE | PARENTID
12345 | 12345ABCDEF
but when i delete the record from dem_comment, (because of the outer join) i m supposed to have something like
NUMPCE | PARENTID
12345 |
but the result is that, no record
NUMPCE | PARENTID
The outer join seems to not work
Thank you for your helpUW (Germany) wrote:
Sorry, I was too fast and did not notice the nested select. Try this:
select dem.NUM_PCE, memo.parentid
from demand dem
left outer join dem_comment memo on CONCAT(dem.NUM_PCE,dem.NUM_DEMANDE) = memo.parentId
where memo.DEM_DATE_CREATION_MEMO is null
or memo.DEM_DATE_CREATION_MEMO = (select MAX(DEM_DATE_CREATION_MEMO)
FROM dem_comment memo
WHERE memo.parentId = CONCAT(dem.NUM_PCE,dem.NUM_DEMANDE));
It is an left outer join, so the predicate on the left table belongs in the on clause
from demand dem
left outer join dem_comment memo
on CONCAT(dem.NUM_PCE,dem.NUM_DEMANDE) = memo.parentId
and
memo.DEM_DATE_CREATION_MEMO = (select MAX(DEM_DATE_CREATION_MEMO)
FROM dem_comment memo
WHERE memo.parentId = CONCAT(dem.NUM_PCE,dem.NUM_DEMANDE)) -
How to use outer join to display the results
I want to develop a report in which the column sequence will be as follows:
1)Item_code
2)Item_name
3)Stock
4)Pending
5)Re-order Level
6)Item_reorder_qty
I had written the query, but the problem is all the products does not get displayed. The products are more than 700. But after running the query, only 364 gets displayed.
How i can make use of outer join in the following statements :
AND ITEM_CODE = LCS_ITEM_CODE
AND ITEM_CODE = PI_ITEM_CODE
AND LCS_ITEM_CODE = PI_ITEM_CODE
in the below given query to solve this.
SELECT
ITEM_CODE,
ITEM_NAME,
((LCS_STK_QTY_BU + LCS_RCVD_QTY_BU - LCS_ISSD_QTY_BU- LCS_REJECT_QTY_BU)/IU_MAX_LOOSE_1)STK ,
SUM(TO_NUMBER(PI_QTY||'.'||PI_QTY_LS) - (PI_GI_QTY_BU/IU_CONV_FACTOR/IU_MAX_LOOSE_1))PNDG,
ITEM_RORD_LVL,
ITEM_RORD_QTY
FROM
OM_ITEM,
OM_ITEM_UOM,
OT_PO_HEAD,
OT_PO_ITEM,
OS_LOCN_CURR_STK
WHERE (ITEM_UOM_CODE = IU_UOM_CODE AND ITEM_CODE = IU_ITEM_CODE)
AND ITEM_CODE = LCS_ITEM_CODE
AND ITEM_CODE = PI_ITEM_CODE
AND LCS_ITEM_CODE = PI_ITEM_CODE
AND LCS_LOCN_CODE ='RM'
AND PI_PH_SYS_ID = PH_SYS_ID
GROUP BY ITEM_CODE,ITEM_NAME,LCS_STK_QTY_BU,LCS_RCVD_QTY_BU,LCS_ISSD_QTY_BU,LCS_REJECT_QTY_BU,IU_MAX_LOOSE_1,ITEM_RORD_LVL,ITEM_RORD_QTY
ORDER BY ITEM_CODE ASC
YogeshAs you have no table aliases I can't tell what columns relate to which tables on your join conditions.
Can you not just put (+) next to the outer joined columns you require on the where clause? Or perhaps consider using ANSI syntax for the joins such as <tableA> LEFT OUTER JOIN <tableB> ON (<join conditions>) -
Outer Join not giving correct result
I have two tables=> tab_child_tmp (product_id,region,child_val,mst_product) and
tab_master_tmp (master_product_id,region,master_val)
tab_child_tmp.mst_product is the foreign key referencing tab_master_tmp.master_product_id.
Currently the tables are populated with below values
tab_child_tmp
PRODUCT_ID REGION CHILD_VAL MST_PRODUCT
Arm-01, CAL, 100, Arm-Master
Arm-01, DEL, 222, Arm-Master
Arm-01, CHEN, 55, Arm-Master
Arm-02, MUM, 69, Arm-Master
Arm-02, DEL, 90, Arm-Master
tab_master_tmp
MST_PRODUCT REGION MASTER_VAL
Arm-Master , CAL, 390
Arm-Master , DEL, 300
Arm-Master, CHEN, 450
Arm-Master, MUM, 600
Now I want to display the result in the below format
PRODUCT_ID REGION CHILD_VAL MASTER_VAL
1. Arm-01 , CAL, 100, 390
2. Arm-01 , DEL, 222, 300
3. Arm-01 , CHEN, 55, 450
4. Arm-01 , MUM, 0, 600
5. Arm-02 , MUM, 69, 600
6. Arm-02 , DEL, 90, 300
7. Arm-02 , CHEN, 0, 450
8. Arm-02 , CAL, 0, 390
When I am running the below query it is not returning the above 4,7 and 8 rows. Can you please provide the correct sql to get the above desired output
SELECT
a.product_id,
nvl(a.region,b.region) geo,
nvl(a.child_val,0)match_val,
b.master_val
FROM
tab_child_tmp a,
tab_master_tmp b
WHERE
a.mst_product(+) = b.master_product AND
a.region(+) = b.region
ThanksHi
Thanks for the reply. Please find below the details.
Oracle Version*
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Solaris: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
Create Table Script_
create table TAB_CHILD_TMP
PRODUCT_ID VARCHAR2(50),
REGION VARCHAR2(100),
CHILD_VAL NUMBER,
MST_PRODUCT VARCHAR2(50)
create table TAB_MASTER_TMP
MST_PRODUCT VARCHAR2(50),
REGION VARCHAR2(100),
MASTER_VAL NUMBER
Insert Script_
INSERT INTO tab_child_tmp VALUES ('Arm-01','CAL',100,'Arm-Master');
INSERT INTO tab_child_tmp VALUES ('Arm-01','DEL',222,'Arm-Master');
INSERT INTO tab_child_tmp VALUES ('Arm-01','CHEN',55,'Arm-Master');
INSERT INTO tab_child_tmp VALUES ('Arm-Master','MUM',69,'PLC1');
INSERT INTO tab_child_tmp VALUES ('Arm-Master','DEL',90,'PLC1');
INSERT INTO tab_master_tmp VALUES ('Arm-Master','CAL',390);
INSERT INTO tab_master_tmp VALUES ('Arm-Master','DEL',300);
INSERT INTO tab_master_tmp VALUES ('Arm-Master','CHEN',450);
INSERT INTO tab_master_tmp VALUES ('Arm-Master','MUM',600);
INSERT INTO tab_master_tmp VALUES ('PLC1','MUM',199);
INSERT INTO tab_master_tmp VALUES ('PLC1','DEL',299);
INSERT INTO tab_master_tmp VALUES ('PLC1','CHEN',399);
Expected output logic*
Need to display the product value for each region along with the value of master product for the corresponding product and region. If a product doesn't belong to a particular region, but the corresponding master product is, then that value also needs to be displayed for that product and region with child value as zero.
ie. for product Arm-01 there is no record in tab_child_tmp for region "MUM", but it's master product 'Arm-Master' has a record for region 'MUM' in tab master_tmp table. So in ouput there will be a record for product 'Arm-01' and region-'MUM' with child value as 0 and master value as 600.
Expected Output*
PRODUCT_ID ~~~ REG ~~~ CHILD_VAL ~~~ MASTER_VAL
Arm-01 ~~~ CAL ~~~ 100 ~~~ 390
Arm-01 ~~~ DEL ~~~ 222 ~~~ 300
Arm-01 ~~~ CHEN ~~~ 55 ~~~ 450
Arm-01 ~~~ MUM ~~~ 0 ~~~ 600
Arm-MASTER ~~~ MUM ~~~ 69 ~~~ 199
Arm-MASTER ~~~ DEL ~~~ 90 ~~~ 299
Arm-MASTER ~~~ CHEN ~~~ 0 ~~~ 399
Please help -
Choice of left or right outer join
Hi Experts,
I have a two tables like named as emp demo
desc emp
empname varchar2(50)
empid number
desc demo
empname varchar2(50)
empid number
when i implement the below quries i'm getting the same o/p.
queries like
select e.ename from emp e left outer join demo d on (e.empid=d.empid);
select e.ename from demo d right outer join emp e on (d.empid=e.empid);
In this case which query is most prefer
Thnks in advance
HHi,
943338 wrote:
Hi Experts,
I have a two tables like named as emp demo
desc emp
empname varchar2(50)
empid number
desc demo
empname varchar2(50)
empid number
when i implement the below quries i'm getting the same o/p.Right. You're getting the same error, because there is no ename column. If you change ename to empname, then you'll still get the same results, because
x LEFT OUTER JOIN y ON zis equivalent to
y RIGHT OUTER JOIN x ON zin results and performance.
queries like
select e.ename from emp e left outer join demo d on (e.empid=d.empid);
select e.ename from demo d right outer join emp e on (d.empid=e.empid);
In this case which query is most preferBoth are equally efficient.
Since most people never use RIGHT OUTER JOIN, it might make maintenance eaiser if you don't use it, either. I would use LEFT OUTER JOIN. -
Outer join vs. 'SELECT in SELECT'
Hi All,
I am generally curious about which method to use between a Outer join and 'SELECT in SELECT'. We can have same result with both methods.
My question is, for real life complex queries, which method is more efficiant? less resource intensive? Any thories you guys have?
I am on Oracle 10.2 on lunix.
See my example below
-- First table
create table emp
id number,
name varchar2(1000),
constraint emp_pk primary key ( id )
-- second table. There will be 1 record, for few of the records in EMP table, in this table
create table leave
id number,
emp_id number,
leave_date date,
constraint leave_pk primary key (id),
constraint leave_fk foreign key ( emp_id ) references emp
create index leave_idx_1 on leave ( emp_id ) ;
-- Populate some sample data in there
insert into emp (id, name)
select object_id, object_name from dba_objects where rownum < 10001 ;
declare
cursor c1 is
select id from emp where mod(id,2) = 0 ;
v_id number := 1 ;
v_date DATE := '01-JAN-08';
begin
for c2 in c1
loop
insert into leave values ( v_id, c2.id, v_date );
v_id := v_id + 1;
v_date := v_date + 1;
end loop;
end;
-- Set autotrace
set autotrace traceonly explain
-- =================================
-- Outer join
-- =================================
select e.id, e.name, l.id, l.leave_date
from emp e, leave l
where e.id = l.emp_id (+) ;
-- ===================================
-- select in select to get same results as above outer join
-- ===================================
select e.id, e.name,
(select l.id from leave l where l.emp_id = e.id ) leave_id,
(select l.leave_date from leave l where l.emp_id = e.id ) leave_date
from emp e ;My hidden question, how these two methods internally work? in the plan we can only see something like 'hash join right outer' or something like that. But how exactly outer join is executed? how is the result formed?
I have got following plans for the two methods
SQL> select e.id, e.name, l.id, l.leave_date
2 from emp e, leave l
3 where e.id = l.emp_id (+) ;
Elapsed: 00:00:00.03
Execution Plan
Plan hash value: 98076489
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 5371K| 16 (7)| 00:00:01 |
|* 1 | HASH JOIN RIGHT OUTER| | 10000 | 5371K| 16 (7)| 00:00:01 |
| 2 | TABLE ACCESS FULL | LEAVE | 5012 | 171K| 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | EMP | 10000 | 5029K| 9 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("E"."ID"="L"."EMP_ID"(+))
Note
- dynamic sampling used for this statement
SQL> select e.id, e.name,
2 (select l.id from leave l where l.emp_id = e.id ) leave_id,
3 (select l.leave_date from leave l where l.emp_id = e.id ) leave_date
4 from emp e ;
Elapsed: 00:00:00.18
Execution Plan
Plan hash value: 2670217481
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 5029K| 9 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| LEAVE | 50 | 1300 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | LEAVE_IDX_1 | 20 | | 1 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| LEAVE | 50 | 1100 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | LEAVE_IDX_1 | 20 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMP | 10000 | 5029K| 9 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("L"."EMP_ID"=:B1)
4 - access("L"."EMP_ID"=:B1)
Note
- dynamic sampling used for this statementPlease let me know your thoughts.
Thanks in advanceA better indicator of performance would be to look at the number of consistent gets that are required to execute the query.
In my environment:
SQL> SELECT * FROM V$VERSION;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for 64-bit Windows: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
SQL> SHOW PARAMETER OPT
NAME TYPE VALUE
filesystemio_options string
object_cache_optimal_size integer 102400
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 10.2.0.4
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_mode string ALL_ROWS
optimizer_secure_view_merging boolean TRUE
plsql_optimize_level integer 2The OUTER JOIN produced the following results:
SQL> select e.id, e.name, l.id, l.leave_date
2 from emp e, leave l
3 where e.id = l.emp_id (+) ;
10000 rows selected.
Execution Plan
Plan hash value: 98076489
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 380K| 9 (12)| 00:00:01 |
|* 1 | HASH JOIN RIGHT OUTER| | 10000 | 380K| 9 (12)| 00:00:01 |
| 2 | TABLE ACCESS FULL | LEAVE | 5017 | 80272 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | EMP | 10000 | 224K| 5 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("E"."ID"="L"."EMP_ID"(+))
Statistics
0 recursive calls
0 db block gets
723 consistent gets
0 physical reads
0 redo size
364047 bytes sent via SQL*Net to client
7672 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processedThe inline subquery produced these results:
SQL> select e.id, e.name,
2 (select l.id from leave l where l.emp_id = e.id ) leave_id,
3 (select l.leave_date from leave l where l.emp_id = e.id ) leave_dat
4 from emp e ;
10000 rows selected.
Execution Plan
Plan hash value: 1706216391
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 224K| 5 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| LEAVE | 1 | 9 | 3 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| LEAVE | 1 | 13 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 10000 | 224K| 5 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("L"."EMP_ID"=:B1)
2 - filter("L"."EMP_ID"=:B1)
Statistics
0 recursive calls
0 db block gets
360705 consistent gets
0 physical reads
0 redo size
364053 bytes sent via SQL*Net to client
7672 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processedSee the 723 consistent gets versus 360705? That is a huge difference.
The second method may be more viable if you create indexes on the columns in the leave table that you are joining to your EMP table.
For example:
SQL> CREATE INDEX LEAD_ID_IDX ON LEAVE(EMP_ID, ID, LEAVE_DATE);
Index created.
SQL> set autotrace traceonly
SQL> select e.id, e.name,
2 (select l.id from leave l where l.emp_id = e.id ) leave_id,
3 (select l.leave_date from leave l where l.emp_id = e.id ) leave_date
4 from emp e ;
10000 rows selected.
Execution Plan
Plan hash value: 1822800249
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 224K| 5 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN | LEAD_ID_IDX | 1 | 9 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | LEAD_ID_IDX | 1 | 13 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 10000 | 224K| 5 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("L"."EMP_ID"=:B1)
2 - access("L"."EMP_ID"=:B1)
Statistics
1 recursive calls
0 db block gets
22111 consistent gets
19 physical reads
0 redo size
364053 bytes sent via SQL*Net to client
7672 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processedThe query improved by a more than a factor of 10 with the index but the consistent gets are still significantly higher then the OUTER JOIN query. Additionally I always try and take the approach when developing queries to minimize the number of table accesses possible. In your second place you have to access the LEAVE table twice, instead of once in the first query. -
Full outer join unexpected results
Warning, long message - I've searched the forums and found nothing similar. I've cut out as much as possible. We have been given the following schema to work with:
CREATE TABLE CALLS (
TRUNKIN VARCHAR2 (10),
TRUNKOUT VARCHAR2 (10),
DURATION FLOAT)
Here is some test data:
insert into calls values(null, 'a', 3);
insert into calls values(null, 'a', 2);
insert into calls values('a', null, 1);
insert into calls values(null, 'a', 0);
insert into calls values(null, 'a', 0);
insert into calls values(null, 'a', 7);
insert into calls values(null, null, 0);
This is horribly unnormalized, but basically this table represent phone calls. trunkin and trunkout represent the two ends, and duration is length of a call. While obviously every call has two ends, the nulls above represent ends we don't care about in this example.
The goal is to end up with data that looks like this. In English, we want the in and out summary statistics for each trunk to be summarized into a single row. (Sorry, these are supposed to be columns, but they got wrapped, so I reposted them as rows):
TRUNKIN a
IN_CALLS_ATTEMPTED 1
IN_CALLS_COMPLETED 1
IN_AVERAGE_DURATION 1
TRUNKOUT a
OUT_CALLS_ATTEMPTED 5
OUT_CALLS_COMPLETED 3
OUT_AVERAGE_DURATION 4
Indeed, with the data given above, these are the results returned with the query at the end of this message. However, when I changed the one non-null trunkin value to null, I got very strange results. First, I independently ran the two subqueries. The first of course returns no rows, the second returns 1 with the same out values above; this is exactly what I would expect. However, when I run the full query, I get **5** rows back, each with just the trunkout column set to "a" and **all** other columns set to null. This makes no sense to me. The 5 rows are obviously the 5 rows from the original data set where trunkout = "a", but I'm not full outer joining those; I'm full outer joining the result of the group by, which only has 1 row. But even given that I'm getting 5 rows back, shouldn't all five of those have the remaining out columns filled in with the values above?
Here is the query:
select
from
SELECT
trunkin as trunk,
COUNT(*) AS in_calls_attempted,
SUM
CASE
WHEN duration > 0 THEN 1
ELSE 0
END
) AS in_calls_completed,
SUM(duration)/
SUM
CASE
WHEN duration > 0 THEN 1
ELSE 0
END
) AS in_average_duration
FROM CALLS
WHERE trunkin IS NOT NULL
GROUP BY trunkin
) callsin
full outer join
SELECT
trunkout as trunk,
COUNT(*) AS out_calls_attempted,
SUM
CASE
WHEN duration > 0 THEN 1
ELSE 0
END
) AS out_calls_completed,
SUM(duration)/
SUM
CASE
WHEN duration > 0 THEN 1
ELSE 0
END
) AS out_average_duration
FROM CALLS
WHERE trunkout IS NOT NULL
GROUP BY trunkout
) callsout
on callsin.trunk = callsout.trunk;I am not entirely sure why you are getting the results you are, but I strongly suspect that it is a result of outer joining on null columns. I would write the query as follows to avoid the outer join problem. The CASE statements in the outer query around the average duration calulations avoid the divide by zero error that would occur when some trunk has only in or out calls.
SELECT trunk,SUM(in_calls_attempted) in_calls_attempted,
SUM(in_calls_completed) in_calls_completed,
CASE WHEN SUM(in_calls_completed) <> 0 THEN
SUM(in_duration)/SUM(in_calls_completed)
ELSE 0 END ave_in_duration,
SUM(out_calls_attempted) out_calls_attempted,
SUM(out_calls_completed) out_calls_completed,
CASE WHEN SUM(out_calls_completed) <> 0 THEN
SUM(out_duration)/SUM(out_calls_completed)
ELSE 0 END ave_out_duration
FROM (
SELECT trunkin trunk,COUNT(*) in_calls_attempted,
SUM(CASE WHEN duration > 0 THEN 1 ELSE 0 END) in_calls_completed,
SUM(duration) in_duration,0 out_calls_attempted,
0 out_calls_completed,0 out_duration
FROM calls
GROUP BY trunkin
UNION ALL
SELECT trunkout trunk,0 in_calls_attempted,0 in_calls_completed,
0 in_duration,COUNT(*) out_calls_attempted,
SUM(CASE WHEN duration > 0 THEN 1 ELSE 0 END) out_calls_completed,
SUM(duration) out_duration
FROM calls
GROUP BY trunkout)
GROUP BY trunkTTFN
John -
Do Outer Joins as well as Self Joins Affect the Performence of a Query ??
4 Tables A,B,C,D.
1 View V Based
Each of the tables having 1 and only one primary key and a few NOT NULL columns.
Now my Query selects from A,B,C,D,V with mapping Table A columns with all other Table(B,C,D,V) Primary Key Columns using Left Outer Join.
Select A.a1,A.a2,A.a3,A.a4,B1.ba,B2.bb,B3.bc,B4.bd,C.c1,D.d1 from (((((((A left outer join B B1 on A.ba=B1.ba) left outer join B B2 on A.bb=B2.bb) left outer join B B3 on A.bc=B3.bc)left outer join B B4 on A.bd=B4.bd)left outer join C on A.c1=C.c1)left outer join D on A.d1=D.d1) left outer join V on A.v1 = V.v1) order by 1;
In this case will the query design effect the Performence???... As this query is taking a long time. As for as Indexes are there on these tables only default Indexes due to Primary, Unique as well as Foreign key only.... Hence table structure is very simple and straight. I need a suggession in such a manner that without making changes to the Table (I am not even allowed to include a single Index to them) ...can the query be modified to optimise the performence??Each change to a query can effect the performance.
Your query looks straight and simple. Maybe you could increase the performance by simply removeing the order by criteria.
This requires a sort and a sort can be slow, especially when the resulting dataset is very large.
If there are indexes on all foreign keys and you join using those FKs then there should be no problem with the index structure.
I can't say whether it would be better to use an index or not. but you can look at the execution plan and check what the CBO wants to do.
Make sure that all statistics are up to date. You could consider to run an additional dbms_stats.gather_table_stats with compute in the test environment, just to see if the execution plan changes after this.
For further ideas search this forum for the thread "When your query takes too long". -
Merging two complemental result sets... or OUTER JOINs not working?
Dear experts!
Again I have a very difficult problem for which I ask Your help, but this time I am better prepared than last time and can deliver sample data of my (hopefully not too much) simplified example:
create table Subjects(
pk_id number not null primary key,
title varchar2(128)
create table People(
pk_id number not null primary key,
name varchar2(128)
create table Results(
pk_id number not null primary key,
fk_subjects_id number,
fk_people_id number,
result number
insert into Subjects(pk_id, title) values (1, 'Choosing a recipe')
insert into Subjects(pk_id, title) values (2, 'Shopping ingredients')
insert into Subjects(pk_id, title) values (3, 'Preparations')
insert into Subjects(pk_id, title) values (4, 'Cooking for beginners')
insert into Subjects(pk_id, title) values (5, 'Eating for pros')
insert into Subjects(pk_id, title) values (6, 'Dishwashing for everyone')
insert into Subjects(pk_id, title) values (7, 'Digesting for experts')
insert into Subjects(pk_id, title) values (8, 'Becoming hungry again...')
insert into Subjects(pk_id, title) values (9, 'Redo from start')
insert into People(pk_id, name) values (1, 'Hank')
insert into People(pk_id, name) values (2, 'Cloe')
insert into People(pk_id, name) values (3, 'Mary')
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (1, 1, 1, 2)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (2, 2, 1, 4)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (3, 3, 1, 3)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (4, 9, 1, 5)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (5, 1, 2, 4)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (6, 2, 2, 1)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (7, 3, 2, 5)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (8, 4, 2, 2)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (9, 5, 2, 3)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (10, 6, 2, 2)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (11, 7, 2, 1)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (12, 4, 3, 3)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (13, 5, 3, 5)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (14, 7, 3, 1)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (15, 8, 3, 5)
insert into Results(pk_id, fk_subjects_id, fk_people_id, result) values (16, 9, 3, 1)
Please imagine this as an university for amateur cooks. Now I want to present them their performance record/"scorecard", for every student, only with her or his marks. On this performance record there should be a list of all 9 subjects possible to pass, and where students got a result, that result should be filled in. I thought that should be possible to achieve with something like this:
SELECT PEOPLE.NAME, SUBJECTS.TITLE, RESULTS.RESULT FROM RESULTS
JOIN PEOPLE ON PEOPLE.PK_ID = RESULTS.FK_PEOPLE_ID
JOIN SUBJECTS ON SUBJECTS.PK_ID = RESULTS.FK_SUBJECTS_ID
WHERE RESULTS.FK_PEOPLE_ID = 2
But also using (LEFT|RIGHT|FULL) OUTER JOINs here does not help me to get what I want, I always only get
NAME TITLE RESULT
Cloe Choosing a recipe 4
Cloe Shopping ingredients 1
Cloe Preparations 5
Cloe Cooking for beginners 2
Cloe Eating for pros 3
Cloe Dishwashing for everyone 2
Cloe Digesting for experts 1
But I want:
NAME TITLE RESULT
Cloe Choosing a recipe 4
Cloe Shopping ingredients 1
Cloe Preparations 5
Cloe Cooking for beginners 2
Cloe Eating for pros 3
Cloe Dishwashing for everyone 2
Cloe Digesting for experts 1
Cloe Becoming hungry again...
Cloe Redo from start
Without having to fill in empty rows for all students which did not take all exams yet.
Is it possible? If so, how?
Thank You very much in advance and Happy Easter to everyone! :-)
With kind regards,
Chriss
Edited by: user9355711 on 01.04.2010 07:01
Edited by: user9355711 on 01.04.2010 07:28
Edited by: user9355711 on 01.04.2010 07:29Also;
var n number
exec :n := 2;
PL/SQL procedure successfully completed
n
2
select ppl.name, sub.title, res.result
from subjects sub, people ppl, results res
where sub.pk_id = res.fk_subjects_id(+)
and ppl.pk_id = :n
and res.fk_people_id(+) = :n
order by sub.title;
NAME TITLE RESULT
Cloe Becoming hungry again...
Cloe Choosing a recipe 4
Cloe Cooking for beginners 2
Cloe Digesting for experts 1
Cloe Dishwashing for everyone 2
Cloe Eating for pros 3
Cloe Preparations 5
Cloe Redo from start
Cloe Shopping ingredients 1 -
View with outer join results wrong number of rows
Hi,
When i run a query on a view it returns 2 rows(2 distinct rows), when i run the same query with the select statement which the view is created , it returns only 1 row. According to data the 1 row result is correct, how come twi results. A coding sample as follows. Any help is most appreciated.
I have a view created based on a outer join of two views in the format;
create or replace view view1 as
select ord.order_no order_no,
ord.del_type del_type,
det.qty qty
from detail_view det, order_view ord
where det.site(+) = ord.site
and det.part(+) = ord.part
and nvl(ord.del_type,'_NULL_') <> 'F'
with read only;
detail_view & order_view themselves have several group by/sum and union Alls.
When i run the query on this view
[Select * from View1 where order_no = 'A30' And del_type = 'B']
it returns 2 distinct rows. But when i run the select statement which created the View1 with the query it returns only one row!!
What did i do wrong?
Thanks
SanjeewaI cannot reproduce this :
SCOTT@LSC01> create table detail_view(qty number,site number,part number);
Table created.
SCOTT@LSC01> create table order_view(order_no varchar2(10), del_type varchar2(1), site number,part number);
Table created.
SCOTT@LSC01>
SCOTT@LSC01> create or replace view view1 as
2 select ord.order_no order_no,
3 ord.del_type del_type,
4 det.qty qty
5 from detail_view det, order_view ord
6 where det.site(+) = ord.site
7 and det.part(+) = ord.part
8 and nvl(ord.del_type,'_NULL_') <> 'F'
9 with read only;
View created.
SCOTT@LSC01>
SCOTT@LSC01> insert into order_view values ('A30','B',1,2);
1 row created.
SCOTT@LSC01> insert into order_view values ('A30','B',1,2);
1 row created.
SCOTT@LSC01>
SCOTT@LSC01> Select * from View1 where order_no = 'A30' And del_type = 'B';
ORDER_NO D QTY
A30 B
A30 B
SCOTT@LSC01>
SCOTT@LSC01> select ord.order_no order_no,
2 ord.del_type del_type,
3 det.qty qty
4 from detail_view det, order_view ord
5 where det.site(+) = ord.site
6 and det.part(+) = ord.part
7 and nvl(ord.del_type,'_NULL_') <> 'F' ;
ORDER_NO D QTY
A30 B
A30 Bwhat is your version? -
Case statement resulting into Left outer join with other tables
Hi All ,
I am facing a stuation where a Case statement on one of the logical columns in Answers is resulting into a left outer join with a table in the query.
If we remove the case stmt, the table is not being acessed.
The case stmt is a simple one and no other logical column is being accessed in the case stmt.
Please advice .
Thanks.Hi Sai,
No ..we dont have any left outer join ...its just that I am selecting measure from F1 which has a confimred dimension D1 with F2.Now when I dont have case stmt on measure from F1(Case stmt is something like : CASE WHEN "- P table"."P Column" = 'Y' THEN 'Right' ELSE 'Wrong' END), then it doesnt query F2.
However as soon as I introduce the case stmt ,the query creates a left outer join with F2.
Thanks. -
Strange result for outer join with rownum
I'm using rownum in join condition of left outer join query but i'm getting strange results.
Query is:
Select * from table1 left outer join table2 on table1.id = table2.id or rownum=1
Data in table1 is
id
7
8
9
Data in table2 is
id
10
11
12
Result of above query in Oracle 9.2.0.1 is
table1.id table2.id
7 10
7 11
7 12
8 10
8 11
8 12
9 10
9 11
9 12
Even if change is rownum related condition to like rownum >2 even than i'm getting same result.
In case of inner join, the above condition gives results as required.
Can anybody explain the result or is it a bug?could you please explain why you are using rownum.
You may have a look at the following link explaining rownum and you should understand why you got this result, keep in mind that you are using an OR condition.
http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/sql_elements6a.htm#4295 -
How to merge 3 different query results using full outer join?
Hi all This is my my query for 2 results
with t1 as (
select trans.crAcc_id,trans.cr_amt,row_number() over (order by trans.head_id) rn from Acttrans trans,
Acttranhead head where trans.head_id in(select link_id from acttrans where head_id=12) and trans.crAcc_id!=0
and head.head_id=trans.head_id
t2 as (
select trans.drAcc_id,trans.dr_amt,head.[Vouc_No],head.[Vouc_Date] ,head.[Check_No],head.[Check_Date],head.[stat],row_number() over (order by trans.head_id) rn from Acttrans trans,
Acttranhead head where trans.head_id=12 and trans.drAcc_id!=0
and head.head_id=trans.head_id
select t1.crAcc_id, t1.cr_amt,t2.[Vouc_No],t2.[Vouc_Date] ,t2.[Check_No],t2.[Check_Date],t2.[stat],t2.drAcc_id,t2.dr_amt from t1
full outer join t2 on t1.rn = t2.rn
Query 3: SELECT [CrAcc_Id] FROM [KSSDATA].[dbo].[ActTrans] where head_id=12 and crAcc_id!=0
and i want to add Query3 result to the ABOVE RESULT but i am unable add third result using full outer join
Thanks
Balu D>>>but i am unable add third result using full outer join
Do you get the error or wrong result?
Best Regards,Uri Dimant SQL Server MVP,
http://sqlblog.com/blogs/uri_dimant/
MS SQL optimization: MS SQL Development and Optimization
MS SQL Consulting:
Large scale of database and data cleansing
Remote DBA Services:
Improves MS SQL Database Performance
SQL Server Integration Services:
Business Intelligence -
ORA-30563, Outer Join not allowed in select list
I can not find any information about this error message that I am getting.
I have just upgraded my Oracle database from Version 7.3 to Version 8.1.7, a stored procedure that was written in v7.3 has outer joins in the select statement.
when trying to run this proc in version 8 I get this meesage.(ORA-30563, Outer Join not allowed in select list)
code ex:
Select alt.id
decode(alt.advise, NULL, NULL, AA.act_yr(+))||'-'||AA.act_per(+)||'-'||AA.Acc_per_no(+)) as advise_no
from alt, AA;
Is there any information about this message anywhere? or does anybody know if this is a known issue with oracle ver 8.1.7?
Thanks
CJIt appears to have been a bug in 7.x
From a metalink note on bugs fixed in 8i (doc 132632.1)
974742 Oracle does not report an error if (+) is specified in select-list. The OUTER JOIN operator (+) is only valid in WHERE clause predicates. As this is not flagged as an error the query can give unexpected results. The correct action to avoid this problem is to fix the query.
Ken
Maybe you are looking for
-
How to do a 3rd party sales process
How to do 3rd party sales process..... plz reply me with the full configuration.....
-
" NOKIA X2 " How to Hide Files (Photos/Videos) fro...
To All Nokia X2 Gallery Sufferers!!! I bought my NOKIA X2 over the weekend, and the problem of Hiding my files from the Gallery view has plagued me ever since I held this phone in my hand... The Gallery is excellent for certain things, and I quite l
-
Trying to find the location for getting started with hootbar
I added the hootbar addon and on the information page about the addon it said you could go to the getting started page to find information on how to use hootbar but I can't locate the page
-
Why is YYYYMM date in flat file coming out in Preview as YYMMYY ?
Hi, The date in the flat file is 200707 but when previewed, it comes up as 070720 I previewed a previous successful load and the data in the preview was 200706. I then copied the row and pasted it in Excel and saved as .CSV and then previewed this ne
-
I need help on a view filter. I tried it via view UI setting but does not work. Then I am working in designer with the following code. I got an error when I open it in browser "Cannot complete this action. Please try again.". I appreciate if someone