This query is giving me an ORA-00920: invalid relational operator error.
I checked for the parenthesis but it looks perfectly fine.
DELETE FROM delete_test d
WHERE d.trans_date, d.item_nbr, d.serial_nbr IN (
SELECT b.trans_date, b.item_nbr, b.serial_nbr FROM (
SELECT a.*, RANK() OVER(PARTITION BY serial_nbr ORDER BY trans_date) rnk
FROM delete_test a) b
WHERE rnk <> 1)
;
Can anyone help me debug it?
You should us extra parenthesis to specify the tuples
try this:
DELETE FROM delete_test d
WHERE (d.trans_date, d.item_nbr, d.serial_nbr) IN ((
SELECT b.trans_date, b.item_nbr, b.serial_nbr FROM (
SELECT a.*, RANK() OVER(PARTITION BY serial_nbr ORDER BY trans_date) rnk
FROM delete_test a) b
WHERE rnk <> 1))
also after some testing if the tuples is generate by subquery you only need one pair parenthesis, but with plain text like ('a','b','c') you need two pair, but two pair always work so imo just always use two pair.
Related
Why is below an invalid sql statement in mysql. It works perfectly in oracle.
SELECT originalAmount,fees,id FROM
(SELECT originalAmount,fees,id, ROW_NUMBER() OVER (PARTITION BY transaction_number ORDER BY eventdate ASC) RANK FROM kir_records where customerid= 1704)
WHERE RANK = 1;
I immediately get a syntax error as soon as paste this in mysql workbench.
Error:
Select is invalid at this position. Expecting '(' at first select.
Is there a workaround to make this work ?
try using this query.
SELECT originalAmount,fees,id FROM
((SELECT originalAmount,fees,id, ROW_NUMBER() OVER (PARTITION BY transaction_number ORDER BY eventdate ASC) RANK FROM kir_records where customerid= 1704))
WHERE RANK = 1;
Look like RANK is a reserved word in MySql. Used backquotes (``) around RANK and it worked as expected. One other thing to take care about is that every derived table (AKA sub-query) must indeed have an alias. Dervied Table alias
Here is the query which worked for me :
SELECT originalAmount,fees,id FROM
(SELECT originalAmount,fees,id, ROW_NUMBER() OVER (PARTITION BY transaction_number ORDER BY eventdate ASC) `RANK` FROM kir_records where customerid= 1704) AS SomeAlias
WHERE `RANK` = 1;
Table 1 has duplicate entries in column A with same frequency values. I need to select one random record out of those .If the duplicate entry contain 'unknown' as a column B value ( like in record "d") select one from other rows . I need a select statement which satisfy the above . Thanks .
These conditions can be prioritized using a case expression in order by with a function like row_number.
select A,B,frequency,timekey
from (select t.*
,row_number() over(partition by A order by cast((B = 'unknown') as int), B) as rnum
from tbl t
) t
where rnum = 1
Here for each group of A rows, we prioritize rows other than B = 'unknown' first, and then in the order of B values.
Use row_number analytic function. If you want to select not unknown record first, then use the query below:
select A, B, Frequency, timekey
from
(select
A, B, Frequency, timekey,
row_number() over(partition by A,Frequency order by case when B='unknown' then 1 else 0 end) rn
)s where rn=1
And if you want to select unknown if they exist, use this row_number in the query above:
row_number() over(partition by A,Frequency order by case when B='unknown' then 0 else 1 end) rn
I'm trying to get the maximum value of a count. The code is as follows
SELECT coachID, COUNT(coachID)
FROM coaches_awards GROUP BY coachID
HAVING COUNT(coachID) =
(
SELECT MAX(t2.awards)
FROM (
SELECT coachID, count(coachID) as awards
FROM coaches_awards
GROUP BY coachID
) t2
);
Yet something keeps failing. The inner query works and gives the answer that I want and the outer query will work if the inner query is replaced by the number required. So I'm assuming I've made some syntax error.
Where am I going wrong?
If you are just looking for one row, why not do:
SELECT coachID, COUNT(coachID) as cnt
FROM coaches_awards
GROUP BY coachID
ORDER BY cnt DESC
LIMIT 1;
If you want ties, then use RANK() or DENSE_RANK():
SELECT ca.*
FROM (SELECT coachID, COUNT(*) as cnt,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM coaches_awards
GROUP BY coachID
) ca
WHERE seqnum = 1;
Does this query use correct Oracle syntax?
select * from ( ( ( dual a) ) ) where a.dummy = 'X';
It works in 11g and 12c but is it truly valid syntax? Or is this is just a compiler "mistake" that might be fixed in the future, causing the code the fail?
I doubt this is the correct syntax for the following reasons:
It doesn't seem to do anything other than add extra parentheses. Expressions like ((1+2)*3) can obviously benefit from nested parentheses but I don't see how they would ever help the FROM clause. And when I look at the above query the alias "a" looks out of scope.
I cannot find a valid path for this syntax in the SQL Language Reference syntax diagrams. On the other hand, it's easy to see how nested parentheses are permitted for expressions, conditions,
and subqueries. Expressions, conditions, and subqueries are recursive and can contain parentheses, but a join clause is not recursive.
I worry about this because there have been similar cases where invalid syntax worked in one release and then failed in the next. For example: select (select count(*) from (select * from scott.emp where ename = dual.dummy)) from dual;. That query worked in 10.2.0.1.0 but stopped working in later versions because table references are scoped to only one level deep.
The original query has a bad style but it's not worth changing our production queries unless there is a real problem with it.
Is the query invalid? Or is there some legitimate reason for that syntax, or is there some path in the syntax diagrams I'm missing?
It is legal syntax to use parenthesis in a join clause in a FROM, and the parentheses do have an effect.
Consider this query:
WITH table_a AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 30),
table_b as ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 20),
table_c AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 10)
SELECT a.id, b.id, c.id
FROM table_a a left join ( table_b b inner join table_c c ON c.id = b.id ) ON b.id = a.id
ORDER BY 1,2,3;
The parenthesis allow you to do an inner join of tables b and c and then outer join that to a.
Without the parenthesis, trying to express that as a left join would be impossible. You either wouldn't get rows 11-30 from table a or else rows 11-20 of table c would be nulls (depending on how you tried to do it).
Note that the above query is equivalent to:
WITH table_a AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 30),
table_b as ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 20),
table_c AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 10)
SELECT a.id, b.id, c.id
FROM table_b b inner join table_c c on c.id = b.id right join table_a a on a.id = b.id
ORDER BY 1,2,3;
, which doesn't require parenthesis. So if you really want to avoid using parentheses in the FROM clause, you usually can do so. Personally, I prefer the LEFT JOIN method with parentheses instead of a RIGHT JOIN.
According to my reading of the syntax diagram for a SELECT statement, putting parentheses around a table reference in a SELECT statement is not allowed. As to whether or not Oracle might "fix" things in a way that would make this invalid, I have no way of knowing but I consider it unlikely. YMMV.
Best of luck.
EDIT
Just for fun I thought I'd put down my reading of the syntax diagram:
As other have noted, parentheses are allowed around a join_clause, but dual a is not a join_clause. Rather, it is a query_table_expression which is part of a table_reference. dual a cannot be a join_clause - to be such it would have to be followed by an inner_join_clause (e.g. INNER JOIN) or an outer_join_clause (e.g. LEFT OUTER JOIN, RIGHT OUTER JOIN or FULL OUTER JOIN), which it is not. Per the syntax diagram parentheses are not allowed around a query_table_expression unless the query_table_expression is preceded by ONLY, and in OP's query dual a is not preceded by ONLY. Thus I conclude that per the Oracle syntax diagrams ( ( (dual a) ) ) is not syntactically correct; however, the database seems to disagree. :-)
Additional to join_clause the subquery may be nested.
So this is perfect valid syntax
(((select * from dual)));
This provides the clue to the validity of the synax of the questioned query.
select * from (((dual)));
Starting with the select we go to query_block
select --> subquery --> query_block
query_block expands to
SELECT * FROM table_reference
From table_reference we step down to (nested) subquery, which can be further nested.
table_reference --> query_table_expression --> ( subquery )
So keep expanding subquery to get required nesting and finaly choose TABLE as the expansion of the query_table_expression
But as MT0 and others noted, this unfortunately don't lead to the e3xpected result. The maximal legal query is
select * from (((select * from dual)));
Can you use something on the line of
Select * from table(cast(select * from tab1 inner join tab2)) inner join tab3
Take into account that what's inside the table(cast()) is something much more complex than a simple select involving a block like with test as (select) select *... etc.
I need a simple way to do this preferably without the need for a temporary table.
Thank you.
Database: Oracle 10g
LE:
I have something like
Select a.dummy1, a.dummy2, wm_concat(t2.dummy3)
from table1 a,
(with str as
(Select '1,2,3,4' from dual)
Select a.dummy1, t.dummy3
from table1 a
inner join
(Select regexp_substr (str, '[^,]+', 1, rownum) split
from str
connect by level <= length (regexp_replace (str, '[^,]+')) + 1) t
on instr(a.dummy2, t.split) > 0) t2
where a.dummy1='xyz'
group by a.dummy1, a.dummy2
The main idea is that column t2.dummy3 contains CSVs. Thats why i have select '1,2,3,4' from dual.
I need to find all rows that contain at least one of the values from str.
Using any kind of loop is out of the question because further i need to integrate this into a larger query used for a report in SSRS, and the tables needed for this are quite large (>1mil rows)
CAST seem completely irrelevant here. You use CAST to change the perceived datatype of an expression. Here, you're passing it a result set, not an expression, and you're not saying what datatype to cast to.
You should be able to simply remove the TABLE and CAST calls and do something like:
SELECT * FROM (SELECT * FROM tab1 INNER JOIN tab2 ON ...) INNER JOIN tab3 ON ...
e.g.
SELECT * FROM
(SELECT d1.dummy FROM dual d1 INNER JOIN dual d2 ON d1.dummy=d2.dummy) d12
INNER JOIN dual d3 ON d12.dummy = d3.dummy
Subquery factoring should work fine here as well.
WITH x AS (SELECT * FROM DUAL)
SELECT * FROM
(SELECT d1.dummy FROM x d1 INNER JOIN x d2 ON d1.dummy=d2.dummy) d12
INNER JOIN dual d3 ON d12.dummy = d3.dummy;
If you're having difficulty getting that kind of construct to work, try adding more detail to your question about specifically what you've tried and what error you're getting.
Yeah... i found the answer... i was just too SQL n00b to see it as it was right in front of me...
i just took the "with" statement outside of the query and it worked.
thank you so much for your help, it was your answer that led me to see my mistake :D
Something like:
with str as
(Select '1,2,3,4' from dual)
Select a.dummy1, a.dummy2, wm_concat(t2.dummy3)
from table1 a,
(
Select a.dummy1, t.dummy3
from table1 a
inner join
(Select regexp_substr (str, '[^,]+', 1, rownum) split
from str
connect by level <= length (regexp_replace (str, '[^,]+')) + 1) t
on instr(a.dummy2, t.split) > 0) t2
where a.dummy1='xyz'
group by a.dummy1, a.dummy2