I have a SQL query that works perfectly in SQL Server, but it fails on Oracle and, in my opinion, it shouldn't.
This is the example to reproduce it:
CREATE TABLE TEST
( TEST_ID NUMBER(37,0) NOT NULL,
TEST_NAME VARCHAR2(50 BYTE),
TEST_GROUP VARCHAR2(20 BYTE),
CONSTRAINT TEST_PK PRIMARY KEY (TEST_ID) );
INSERT INTO TEST (TEST_ID, TEST_NAME) VALUES (1, 'TEST 1');
INSERT INTO TEST (TEST_ID, TEST_NAME, TEST_GROUP) VALUES (2, 'TEST 2', 'A');
INSERT INTO TEST (TEST_ID, TEST_NAME, TEST_GROUP) VALUES (3, 'TEST 3', 'B');
INSERT INTO TEST (TEST_ID, TEST_NAME, TEST_GROUP) VALUES (4, 'TEST 4', 'A');
This query returns the expected information:
SELECT TEST_GROUP, COUNT(R$), MIN(R$) R$_A, MAX(R$) R$_Z
FROM (
SELECT MAIN.*, ROW_NUMBER() OVER (ORDER BY TEST_GROUP, TEST_ID) R$
FROM ( SELECT TEST_ID, TEST_NAME, TEST_GROUP
FROM TEST
GROUP BY TEST_ID, TEST_NAME, TEST_GROUP
) MAIN
) MAIN
GROUP BY TEST_GROUP
It returns three TEST_GROUPS with the right calculations.
TEST_GROUP COUNT(R$) R$_A R$_Z
-------------- --------- ------- -------
A 2 1 2
B 1 3 3
(null) 1 4 4
Explain Plan:
OPERATION OBJECT_NAME CARDINALITY COST
SELECT STATEMENT 4 3
SORT (GROUP BY NOSORT) 4 3
VIEW 4 3
WINDOW (NOSORT) 4 3
SORT (GROUP BY) 4 3
TABLE ACCESS (FULL) TEST 4 3
Other XML
{info}
info type="db_version"
12.1.0.1
info type="parse_schema"
"BABTEC"
info type="dynamic_sampling"
2
info type="plan_hash"
1486410247
info type="plan_hash_2"
1249517352
{hint}
FULL(@"SEL$335DD26A" "TEST"@"SEL$3")
NO_ACCESS(@"SEL$1" "MAIN"@"SEL$1")
OUTLINE(@"SEL$3")
OUTLINE(@"SEL$2")
OUTLINE_LEAF(@"SEL$1")
MERGE(@"SEL$3")
OUTLINE_LEAF(@"SEL$335DD26A")
ALL_ROWS
DB_VERSION('12.1.0.1')
OPTIMIZER_FEATURES_ENABLE('12.1.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
But if we change the sorting in the ROW_NUMBER
(by changing from the default ASC to DESC) it does not:
SELECT TEST_GROUP, COUNT(R$), MIN(R$) R$_A, MAX(R$) R$_Z
FROM (
SELECT MAIN.*, ROW_NUMBER() OVER (ORDER BY TEST_GROUP **DESC**, TEST_ID) R$
FROM ( SELECT TEST_ID, TEST_NAME, TEST_GROUP
FROM TEST
GROUP BY TEST_ID, TEST_NAME, TEST_GROUP
) MAIN
) MAIN
GROUP BY TEST_GROUP;
It only returns a single group.
TEST_GROUP COUNT(R$) R$_A R$_Z
-------------- --------- ------- -------
A 4 1 4
Explain Plan:
OPERATION OBJECT_NAME CARDINALITY COST
SELECT STATEMENT 4 3
HASH(GROUP BY) 4 3
VIEW 4 3
WINDOW (NOSORT) 4 3
SORT (GROUP BY) 4 3
TABLE ACCESS (FULL) TEST 4 3
Other XML
{info}
info type="db_version"
12.1.0.1
info type="parse_schema"
"BABTEC"
info type="dynamic_sampling"
2
info type="plan_hash"
1128091058
info type="plan_hash_2"
3776505473
{hint}
FULL(@"SEL$335DD26A" "TEST"@"SEL$3")
NO_ACCESS(@"SEL$1" "MAIN"@"SEL$1")
OUTLINE(@"SEL$3")
OUTLINE(@"SEL$2")
OUTLINE_LEAF(@"SEL$1")
MERGE(@"SEL$3")
OUTLINE_LEAF(@"SEL$335DD26A")
ALL_ROWS
DB_VERSION('12.1.0.1')
OPTIMIZER_FEATURES_ENABLE('12.1.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
Notice that to reproduce the problem, it is required that the most internal query has a GROUP BY
expression. If not, the result is the one we expect:
SELECT TEST_GROUP, COUNT(R$), MIN(R$) R$_A, MAX(R$) R$_Z
FROM (
SELECT MAIN.*, ROW_NUMBER() OVER (ORDER BY TEST_GROUP DESC, TEST_ID) R$
FROM ( SELECT TEST_ID, TEST_NAME, TEST_GROUP
FROM TEST ) MAIN
) MAIN
GROUP BY TEST_GROUP;
TEST_GROUP COUNT(R$) R$_A R$_Z
----------------------------------------
(null) 1 1 1
B 1 2 2
A 2 3 4
We are using Oracle Database 12c Release 12.1.0.1.0 - 64bit
There is a workaround for this problem that is add an ORDER BY
clause after the GROUP BY, but this is only valid in Oracle, it fails in SQLServer. The query will be:
SELECT TEST_GROUP, COUNT(R$), MIN(R$) R$_A, MAX(R$) R$_Z
FROM (
SELECT MAIN.*, ROW_NUMBER() OVER (ORDER BY TEST_GROUP DESC, TEST_ID) R$
FROM ( SELECT TEST_ID, TEST_NAME, TEST_GROUP
FROM TEST
GROUP BY TEST_ID, TEST_NAME, TEST_GROUP
ORDER BY TEST_GROUP DESC ) MAIN
) MAIN
GROUP BY TEST_GROUP;
TEST_GROUP COUNT(R$) R$_A R$_Z
-------------- --------- ------- -------
(null) 1 1 1
B 1 2 2
A 2 3 4
Any help will be appreciated