Oracle sql missing right parenthesis - sql

I'm trying to limit the number of rows that would be displayed when I run my query.
When I run the code below in SQL developer, it returns missing right parenthesis error..
select * from
(select row_number() over (order by rescode) rnum, a.* from
(
SELECT *
FROM trans z
LEFT JOIN emails a
ON z.email1_hist_id=a.email_id
or z.email2_hist_id=a.email_id
) a
) where rnum between 1 and 50;
I tried running the inside query:
SELECT *
FROM trans z
LEFT JOIN emails a
ON z.email1_hist_id=a.email_id
or z.email2_hist_id=a.email_id
and it works fine. On the other hand I tried removing the OR portion of my query and included the limit rows query and it returns the number of rows I specified.
What exactly is wrong in my code?

This should work - you don't need two levels of subquery
select *
from
( SELECT *, row_number() over (order by rescode) rnum
FROM trans z
LEFT JOIN emails a
ON (z.email1_hist_id=a.email_id or z.email2_hist_id=a.email_id)
) x
where rnum between 1 and 50;
Also, make sure there are no duplicate column names between trans and emails - this will trip the query because * from the inner query cannot return duplicate names.

My best guess is that it doesn't like your giving the sub-selection an alias, so it's throwing the syntax error at the "a" in ") a )".

I don't recall about Oracle, but I know that MySQL actually requires sub-selections to have an alias. I'd try adding one to your outer sub-select (before the where rnum...).

Related

How to join in SQL-SERVER

I am trying to learn SQL-SERVER and I have created the below query:
WITH T AS
(
SELECT ROW_NUMBER() OVER(ORDER BY d.DIALOG_ID) as row_num, *
FROM test.db as d
INNER JOIN test.dbs as ds
ON d.DIALOG_ID = ds.DIALOG_ID
)
SELECT *
FROM T
WHERE row_num <=10;
I found that the only way to limit is with ROW_NUMBER().
Although when I try to run the join I have this error:
org.jkiss.dbeaver.model.sql.DBSQLException: SQL Error [8156] [S0001]: The column 'DIALOG_ID' was specified multiple times for 'T'.
The problem: In the WITH, you do SELECT * which gets all columns from both tables db and dbs. Both have a column DIALOG_ID, so a column by that name ends up twice in the result set of the WITH.
Although until here that is all allowed, it is not good practice: why have the same data twice?
Things go wrong when SQL Server has to determine what SELECT * FROM T means: it expands SELECT * to the actual columns of T, but it finds a duplicate column name, and then it refuses to continue.
The fix (and also highly recommended in general): be specific about the columns that you want to output. If T has no duplicate columns, then SELECT * FROM T will succeed.
Note that the even-more-pure variant is to also be specific about what columns you select from T. By doing that it becomes clear at a glance what the SELECT produces, instead of having to guess or investigate when you look at the query later on (or when someone else does).
The updated code would look like this (fill in your column names as we don't know them):
WITH T AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY d.DIALOG_ID) as row_num,
d.DIALOG_ID, d.SOME_OTHER_COL,
ds.DS_ID, ds.SOME_OTHER_COL_2
FROM test.db AS d
INNER JOIN test.dbs AS ds ON d.DIALOG_ID = ds.DIALOG_ID
)
SELECT row_num, DIALOG_ID, SOME_OTHER_COL, DS_ID, SOME_OTHER_COL_2
FROM T
WHERE row_num <= 10;
WITH T AS
(
SELECT ROW_NUMBER() OVER(ORDER BY d.DIALOG_ID) as row_num, d.*
FROM test.db as d
INNER JOIN test.dbs as ds
ON d.DIALOG_ID = ds.DIALOG_ID
)
SELECT *
FROM T
WHERE row_num <=10;

How to properly select just a number of rows in between in Oracle 11.g?

For now this is the code I'm using:
SELECT *
FROM (
SELECT product.*, rownum AS n
FROM product
) WHERE n >= 4 AND n < 4+2;
This selects 2 rows from the table product starting to count by row number 4 (included).
And it works fine BUT the final select will also show a column for the rownum.
The only workaround I have for now is to manually type the columns that I want in the main Select, but what if I didn't know the names and amount of columns?
Is there a nicer way to do this?
Many thanks
If you dont want to write all column names then you need to join your query with your table again using PK. (As I dont think that there is another way in oracle 11g to exclude rn from final result except writing all the column names manually)
SELECT T.* FROM
(SELECT PK_COLUMN
FROM (
SELECT product.PK_COLUMN, rownum AS n
FROM product
) WHERE n >= 4 AND n < 4+2) P
JOIN T ON T.PK_COLUMN = P.PK_COLUMN
Cheers!!
What I am wondering here is, you are not using any ORDER BY clause. Without using ORDER BY clause rows can be returned in any order. So basically your query is similar to -
SELECT product.*
FROM product
WHERE rownum <= 3;

Redshift: Cross join make data disappear

I have a weird issue in Redshift with a crossjoin.
I am generating days and want to join them with some ids.
The sample query is this:
with ids as (
Select number as id
from models.number_10000
limit 10
),
day as (
SELECT
TO_CHAR(DATEADD(day,num.number,CAST(DATEADD(day,-463,GETDATE()) AS DATE)),'YYYY-MM-DD') as date_string
FROM
(Select * from models.number_10000 limit 463)
as num
)
SELECT
id,date_string
from ids,day
Everything is working fine so far.
However, if I group by then I have no results.
with ids as (
Select number as id
from models.number_10000
limit 10
),
day as (
SELECT
TO_CHAR(DATEADD(day,num.number,CAST(DATEADD(day,-463,GETDATE()) AS DATE)),'YYYY-MM-DD') as date_string
FROM
(Select * from models.number_10000 limit 463)
as num
)
SELECT
id,date_String
from ids,day
group by 1,2
How is this happening? I have never faced something similar. I guess it's something with the cross join and the group by but it seems very strange.
Any thoughts?
I'd start with the following:
State your JOIN explicitly (ANSI92 Style).
State the names of items you want to be grouped explicitly.
Moreover - remove your GROUP BY statement (as you do not have any aggregate functions) and have a DISTINCT clause in your select statement.

Outer Query OrderBy does not depends on Inner Query's Resultset

I am not having deep knowledge of SQL execution order.
When I Execute a Query
select top 2 * from Configuration
It Gives me
ABC1,100,Data001
ABC2,200,Data002
When I Execute a Query
select top 2 * from Configuration order by 1 desc
It Gives me
XYZ1,400,Data100
XYZ2,300,Data099
When I Execute a Query
select * from (select top 2 * from Configuration) as a order by 1 desc
It gives me
XYZ1,400,Data100
XYZ2,300,Data099
My problem is why i am getting
XYZ1,400,Data100
XYZ2,300,Data099
as output instead
ABC1,100,Data001
ABC2,200,Data002
As per my knowledge Inner Query Will Return two rows to Outer Query.
Outer Query Will process those two rows with
From->Where->group by->having->Select->Order by
order of Execution and Will give output as two rows which I mentioned as expected. But Outer Query's order by is affecting on whole table of Inner Query.
Please comment where I am making mistake.
SQL Server has no any sense to populate by default order by.
In your inner query you have not specified order by so it returned wrong result.
Now use below code for SQL Server 2008 R2
SELECT * FROM (SELECT TOP 2 * FROM Configuration ORDER BY 1) AS a ORDER BY 1 DESC
One other alternative is : Comman Table Expression , Like below,
;WITH cteTest AS
(
SELECT TOP 2 *
FROM Configuration ORDER BY 1
)
SELECT * FROM cteTest ORDER BY 1 DESC

How to use the result of an SQL statement in a math expression?

I have two SELECT statements that return a number each, and I'd like to divide one by the other.
Something like the following, if it would work:
SELECT
SELECT
SUM(SIZE)
FROM
GLOBAL_STATS_V_M
WHERE
ID IN ("DuplicatedRule", "OldRule", "RevRule", "TmpRule")
/
SELECT
SUM(SIZE)
FROM
GLOBAL_STATS_V_M
WHERE
ID IN ("Total")
That gets a 'Query Error: near "SELECT": syntax error Unable to execute statement'.
Adding parenthesis does not help.
How to do this?
I'm using Sqliteman
You need to add parenthesis:
SELECT
(SELECT
SUM(SIZE)
FROM
GLOBAL_STATS_V_M
WHERE
ID IN ("DuplicatedRule", "OldRule", "RevRule", "TmpRule")
)
/
(SELECT
SUM(SIZE)
FROM
GLOBAL_STATS_V_M
WHERE
ID IN ("Total")
)
Two problems here.
You need parenthesis around both sub select statements.
You need to finish the outer statement with FROM DUAL.
select
(select ....) / (select ....) as total
from
dual
I actually would prefer to write the query differently for cleanliness.
select subtotal.total / alltotal.total
from (select sum(size) as total .... where id in ("Duplic....) ) subtotal,
(select sum(size) as total .... where id in ("total") ) alltotal