How to fix an error when using Alias in Oracle - sql

I am receiving a syntax error when running the following code
42601: syntax error at or near "."
I think it has something to do with the alias but I cannot see where the problem is.
SELECT * FROM (
SELECT
m.shipment_id
m.route_id,
m.leg_sequence_id,
m.leg_warehouse_id,
m.leg_ship_method,
row_number() over (partition by m.route_id order by m.leg_sequence_id desc) as rn
FROM posimorders.sc_execution_eu.o_detailed_routes_v2 m
)
WHERE rn=1
LIMIT 100;

Your code includes:
SELECT * FROM (
SELECT
m.shipment_id
m.route_id,
...
You are missing a comma after m.shipment_id so it is trying to interpret m.route_id as a column alias for the shipment ID, which isn't what you intended; and an alias is a single identifier rather than a dot-separated hierarchy. Hence the error you are seeing, though that isn't coming from Oracle itself - your client seems to be parsing it first.
Oracle also doesn't support LIMIT, but from 12c it has a row-limiting clause you can use instead:
SELECT * FROM (
SELECT
m.shipment_id,
m.route_id,
m.leg_sequence_id,
m.leg_warehouse_id,
m.leg_ship_method,
row_number() over (partition by m.route_id order by m.leg_sequence_id desc) as rn
FROM posimorders.sc_execution_eu.o_detailed_routes_v2 m
)
WHERE rn=1
FETCH FIRST 100 ROWS ONLY;
or WITH TIES if you prefer.
The three levels in posimorders.sc_execution_eu.o_detailed_routes_v2 looks wrong too though... see the docs.

Related

weird error in hive query:SemanticException Failed to breakup Windowing invocations into Groups

I want a set of random data from hive, for example row_number between 772001 and 773000.
My sql is as below:
select * from (
select *, row_number() over (order by `name`) as row_dsa
from `jck_bonc_demo`.`frjc_jbxx`
)tmp_table where row_dsa between 772001 and 773000
and I get the following error:
[Cloudera][Hardy] (80) Syntax or semantic analysis error thrown in
server while executing query. Error message from server: Error while
compiling statement: FAILED: SemanticException Failed to breakup
Windowing invocations into Groups. At least 1 group must only depend
on input columns. Also check for circular dependencies.
What can I do for this error, anyone can help?
I think this is the syntax you want:
select *
from (select *, row_number() over (order by `name`) as row_dsa
from `jck_bonc_demo`.`frjc_jbxx`
) x
where row_dsa between 772001 and 773000;
You need a subquery to use row_dsa in a where clause.
Use select s.*, ... (with table alias) if you want to select all from table plus one more calculated column, not select *. Also, no need to back-quote non-reserved words:
select *
from (select s.*, row_number() over (order by name) as row_dsa
from jck_bonc_demo.frjc_jbxx s
) x
where row_dsa between 772001 and 773000;
there is a bug in my program,name is not the col of the specified table,the error message is weird. Tanks for your answer #Gordon Linoff #eftjoin

Hive: less than operator error in subquery

I want the latest records from HIVE table using the following query-
WITH lot as (select *
from to_burn_in as a where a.rel_lot='${Rel_Lot}')
select a.* from lot AS a
where not exists (select 1 from lot as b
where a.Rel_Lot=b.Rel_Lot and a.SerialNum=b.SerialNum and a.Test_Stage=b.Test_Stage
and cast(a.test_datetime as TIMESTAMP) < cast(b.Test_Datetime as TIMESTAMP))
order by a.SerialNum
this query is throwing a error as
Error while compiling statement: FAILED: SemanticException line 0:undefined:-1 Unsupported SubQuery Expression 'Test_Datetime': SubQuery expression refers to both Parent and SubQuery expressions and is not a valid join condition.
I have tried running with equal operator in place of the less than operator in subquery and it is running fine. I read the HIVE documentation as given in
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SubQueries
and couldn't figure out why it is throwing a error as 'where' subquery is supported.
What might be the problem here?
EXISTS works the same as a join actually. Not equality join conditions are not supported in Hive prior Hive 2.2.0 (see HIVE-15211, HIVE-15251)
It seems you are trying to get records having latest timestamp per Rel_Lot,SerialNum,Test_Stage. Your query can be rewritten using dense_rank() or rank() function:
WITH lot as (select *
from to_burn_in as a where a.rel_lot='${Rel_Lot}'
)
select * from
(
select a.*,
dense_rank() over(partition by Rel_Lot,SerialNum,Test_Stage order by cast(a.test_datetime as TIMESTAMP) desc) as rnk
from lot AS a
)s
where rnk=1
order by s.SerialNum

"ORDER BY" in subquery - not avaliable in MonetDB?

I found that, when using order-by directly, it is ok.
SELECT t0."D" AS fd,
SUM(t0."SD") AS top
FROM "mock_table_1" AS t0
GROUP BY t0."D"
ORDER BY top ASC
LIMIT 10
but when using it in a subquery, an syntax error is reported.
SELECT * FROM (
SELECT t0."D" AS fd,
SUM(t0."SD") AS top
FROM "mock_table_1" AS t0
GROUP BY t0."D"
ORDER BY top ASC
LIMIT 10
)
here is the error message.
syntax error, unexpected ORDER, expecting UNION or EXCEPT or INTERSECT or ')' in: "select t0."A" as d0,
So, I wonder if monetdb is designed to be like this, or it is a bug?
that is the expected behavior. offset, limit, and order by are not allowed in subqueries
https://www.monetdb.org/pipermail/users-list/2013-October/006856.html
SQL-conforming DBMSes are not supposed to allow ORDER BY in subqueries, because it contradicts the conceptual model of a relational DBMS. See:
Is order by clause allowed in a subquery
for details. A way around that, however, is to use Window Functions, which MonetDB does support. Specifically, in your subquery, instead of, say,
SELECT c1 FROM t1;
you can
SELECT c1, ROW_NUMBER() OVER () as rownum from t1;
and now you have the relative order of the inner query result available to the outer query.

Return Row of Every Nth Record

I'm trying to developer the Oracle SQL version of the accepted answer here:
Return row of every n'th record
What I have so far is:
SELECT ROW_ID, CUST_ACCT_SITE_ID
FROM
(
SELECT CUST_ACCT_SITE_ID as CUST_ACCT_SITE_ID, ROW_NUMBER() OVER (ORDER BY CUST_ACCT_SITE_ID) AS ROW_ID
FROM XXDMX_VOICE_CUSTOMERS_TBL
) AS t
WHERE ROW_ID % 10000 = 0
ORDER BY CUST_ACCT_SITE_ID;
I get the error
ERROR
ORA-00933: SQL command not properly ended
I've tried lots of variations and can't think of what I am doing wrong. Any ideas, Oracle experts?
Try writing the query like this:
SELECT rn, CUST_ACCT_SITE_ID
FROM (SELECT CUST_ACCT_SITE_ID as CUST_ACCT_SITE_ID,
ROW_NUMBER() OVER (ORDER BY CUST_ACCT_SITE_ID) AS rn
FROM XXDMX_VOICE_CUSTOMERS_TBL
) t
WHERE mod(rn, 10000) = 0
ORDER BY CUST_ACCT_SITE_ID;
The primary difference is removing the as for the table alias. Oracle doesn't allow this syntax. I also changed row_id to something else, because "rowid" means something in Oracle and its use could be confusing (see here).
In PL/SQL (the name for "Oracle SQL"), the modulus operator uses this syntax:
WHERE MOD(ROW_ID, 10000) = 0

Why do partitions require nested selects?

I have a page to show 10 messages by each user (don't ask me why)
I have the following code:
SELECT *, row_number() over(partition by user_id) as row_num
FROM "posts"
WHERE row_num <= 10
It doesn't work.
When I do this:
SELECT *
FROM (
SELECT *, row_number() over(partition by user_id) as row_num FROM "posts") as T
WHERE row_num <= 10
It does work.
Why do I need nested query to see row_num column? Btw, in first request I actually see it in results but can't use where keyword for this column.
It seems to be the same "rule" as any query, column aliases aren't visible to the WHERE clause;
This will also fail;
SELECT id AS newid
FROM test
WHERE newid=1; -- must use "id" in WHERE clause
SQL Query like:
SELECT *
FROM table
WHERE <condition>
will execute in next order:
3.SELECT *
1.FROM table
2.WHERE <condition>
so, as Joachim Isaksson say, columns in SELECt clause are not visible in WHERE clause, because of processing order.
In your second query, column row_num are fetched in FROM clause first, so it will be visible in WHERE clause.
Here is simple list of steps in order they executes.
There is a good reason for this rule in standard SQL.
Consider the statement:
SELECT *, row_number() over (partition by user_id) as row_num
FROM "posts"
WHERE row_num <= 10 and p.type = 'xxx';
When does the p.type = 'xxx' get evaluated relative to the row number? In other words, would this return the first ten rows of "xxx"? Or would it return the "xxx"s in the first ten rows?
The designers of the SQL language recognize that this is a hard problem to resolve. Only allowing them in the select clause resolves the issue.
You can check this topic and this one on dba.stockexchange.com about order in which SQL executes SELECT clause. I think it aplies not only for PostgreSQL, but for all RDBMS.