What's wrong with this Oracle query? - sql

Below is a query generated by the PetaPoco ORM for .NET. I don't have an Oracle client right now to debug it and I can't see anything obviously wrong (but I'm a SQL Server guy). Can anyone tell me why it is producing this error:
Oracle.DataAccess.Client.OracleException ORA-00923: FROM keyword not found where expected
SELECT *
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) peta_rn,
"ON_CUST_MAS"."CU_NO",
"ON_CUST_MAS"."CU_NAME",
"ON_CUST_MAS"."CU_TYPE",
"ON_CUST_MAS"."CONTACT",
"ON_CUST_MAS"."ADD1_SH",
"ON_CUST_MAS"."ADD2_SH",
"ON_CUST_MAS"."CITY_SH",
"ON_CUST_MAS"."POST_CODE",
"ON_CUST_MAS"."PROV_SH",
"ON_CUST_MAS"."COUNTRY",
"ON_CUST_MAS"."PHONE_NU",
"ON_CUST_MAS"."FAX_NU",
"ON_CUST_MAS"."EMAIL",
"ON_CUST_MAS"."PU_ORDER_FL",
"ON_CUST_MAS"."CREDIT_AMOUNT"
FROM "ON_CUST_MAS" ) peta_paged
WHERE peta_rn>0 AND peta_rn<=20
Edit: Just in case it helps, this is a paging query. Regular queries (select all, select by ID) are working fine.

The problem is that the SELECT NULL in the ORDER BY clause of your analytic function is syntactically incorrect.
over (ORDER BY (SELECT NULL))
could be rewritten
(ORDER BY (SELECT NULL from dual))
or more simply
(ORDER BY null)
Of course, it doesn't really make sense to get a row_number if you aren't ordering the results by anything. There is no reason to expect that the set of rows that are returned would be consistent-- you could get any set of 20 rows arbitrarily. And if you go to the second page of results, there is no reason to expect that the second page of results would be completely different than the first page or that any particular result would appear on any page if you page through the entire result set.

There should be and order defined within ORDER BY clause. For example, lets say your elements are displayed in order of column "on_cust_mas"."cu_no", than your query should look like:
SELECT *
FROM (SELECT Row_number()
over (
ORDER BY ("on_cust_mas"."cu_no")) peta_rn,
"on_cust_mas"."cu_no",
"on_cust_mas"."cu_name",
"on_cust_mas"."cu_type",
"on_cust_mas"."contact",
"on_cust_mas"."add1_sh",
"on_cust_mas"."add2_sh",
"on_cust_mas"."city_sh",
"on_cust_mas"."post_code",
"on_cust_mas"."prov_sh",
"on_cust_mas"."country",
"on_cust_mas"."phone_nu",
"on_cust_mas"."fax_nu",
"on_cust_mas"."email",
"on_cust_mas"."pu_order_fl",
"on_cust_mas"."credit_amount"
FROM "on_cust_mas") peta_paged
WHERE peta_rn > 0
AND peta_rn <= 20
If this is a different column that sets the order just switch it within ORDER BY clause. In fact there should be any order defined, otherwise it's not guaranteed that it won't change, and you cant be sure what will be displayed at any page.

Related

ROW_NUMBER function does not start from 1

I would like to ask about strange behaviour in SQL Server whilst using ROW_NUMBER() Function. Typically it should start from 1 and Order values by the selected column in Order By clause, which for the most scenarios works for me just as it is supposed to, but I have a particular case when I use a basic Select Statement:
SELECT
ROW_NUMBER() OVER (ORDER BY VIN) AS RN,
*
FROM dbo.RawData
and I get such result:
RN VIN
6301 JTEBR3FJ00K096082
6302 JTEBR3FJ00K096132
6303 JTEBR3FJ00K096146
6304 JTEBR3FJ00K096163
6305 JTEBR3FJ00K096180
6306 JTEBR3FJ00K096275
1801 5TDDZRFHX0S820530
1802 5TDDZRFHX0S824111
1803 5TDDZRFHX0S824500
1804 5TDDZRFHX0S825971
1805 5TDDZRFHX0S826456
and those are the first columns in the return table. The whole ROW_NUMBER function works randomly, after chain from 6301 to 6306, the chain from 1801 to 1940 starts etc.
The VIN column (the one I sort data based on) is set to nvarchar(17)
could you please help with solving the issue which might occur in this case?
I would be grateful for any tips what might be wrong
You can use ORDER BY to order the rows in a desired way:
SELECT ROW_NUMBER() OVER (ORDER BY VIN) AS RN
,*
FROM dbo.RawData
ORDER BY RN;
As the row_number is calculated in the SELECTE, you can use its value in the ORDER BY clause without the need of nested query.

Using Multiple aggregate functions in the where clause

We have a select statement in production that takes quite a lot of time.
The current query uses row number - window function.
I am trying to rewrite the query and test the same. assuming its orc table fetching aggregate values instead of using row number may help to reduce the execution time, is my assumption
Is something like this possible. Let me know if i am missing anything.
Sorry i am trying to learn, so please bear with my mistakes, if any.
I tried to rewrite the query as mentioned below.
Original query
SELECT
Q.id,
Q.crt_ts,
Q.upd_ts,
Q.exp_ts,
Q.biz_effdt
(
SELECT u.id, u.crt_ts, u.upd_ts, u.exp_ts, u.biz_effdt, ROW_NUMBER() OVER (PARTITION BY u.id ORDER BY u.crt_ts DESC) AS ROW_N
FROM ( SELECT cust_prd.id, cust_prd.crt_ts, cust_prd.upd_ts, cust_prd.exp_ts, cust_prd.biz_effdt FROM MSTR_CORE.cust_prd
WHERE biz_effdt IN ( SELECT MAX(cust_prd.biz_effdt) FROM MSTR_CORE.cust_prd )
) U
)Q WHERE Q.row_n = 1
My attempt:
SELECT cust_prd.id, cust_prd.crt_ts, cust_prd.upd_ts, cust_prd.exp_ts, cust_prd.biz_effdt FROM MSTR_CORE.cust_prd
WHERE biz_effdt IN ( SELECT MAX(cust_prd.biz_effdt) FROM MSTR_CORE.cust_prd )
having cust_prd.crt_ts = max (cust_prd.crt_ts)

Teradata error 3504 (non-aggregate values must be part of group) when using windowing function

So I wrote a query that uses a window function and I keep getting an error 3504 in Teradata, eventhough I'm sure I have the correct columns in the group by clause (all non-aggregate columns). It has something to do with the windowing function I'm using, because when I comment it out I don't get the error, but I have no idea how to resolve it.
This is the query:
select
n.acct_id as bd_acct_id
,n.tran_nr as tran_order
,t.trade_dt - n.tran_dt as days_until_trade
,n.n_total
,sum(t.trade_ct) as trades_ct
,sum(t.trade_gross_am) as tot_trades
,sum(t.trade_gross_am) over (partition by bd_acct_id, tran_order order by tran_order) as running_total
from nnae n
left join trades t
on n.acct_id = t.acct_id
having days_until_trade > 0
group by 1,2,3,4
order by 1,2,3
Would appreciate any help. Thanks!
Presumably, you intend something like this:
sum(sum(t.trade_gross_am)) over (partition by n.acct_id, n.tran_nr
order by min(n.tran_dt)
rows between unbounded preceding and current row
) as running_total
It seems odd to have a running total, without the date column explicitly in the result set.
Also, I replaced the aliases with the original column names. Not all databases support aliases in window functions, so this is just a habit I'm used to.

Split the results of a query in half

I'm trying to export rows from one database to Excel and I'm limited to 65000 rows at a shot. That tells me I'm working with an Access database but I'm not sure since this is a 3rd party application (MRI Netsource) with limited query ability. I've tried the options posted at this solution (Is there a way to split the results of a select query into two equal halfs?) but neither of them work -- in fact, they end up duplicating results rather than cutting them in half.
One possibly related issue is that this table does not have a unique ID field. Each record's unique ID can be dynamically formed by the concatenation of several text fields.
This produces 91934 results:
SELECT * from note
This produces 122731 results:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY notedate) AS rn FROM note
) T1
WHERE rn % 2 = 1
EDIT: Likewise, this produces 91934 results, half of them with a tile_nr value of 1, the other half with a value of 2:
SELECT *, NTILE(2) OVER (ORDER BY notedate) AS tile_nr FROM note
However this produces 122778 results, all of which have a tile_nr value of 1:
SELECT bldgid, leasid, notedate, ref1, ref2, tile_nr
FROM (
SELECT *, NTILE(2) OVER (ORDER BY notedate) AS tile_nr FROM note) x
WHERE x.tile_nr = 1
I know that I could just use a COUNT to get the exact number of records, run one query using TOP 65000 ORDER BY notedate, and then another that says TOP 26934 ORDER BY notedate DESC, for example, but as this dataset changes a lot I'd prefer some way to automate this to save time.

Why does ROW_NUMBER OVER (ORDER BY column) return a different result order than just ORDER BY column?

I'm on SQL Server 2008, using NHibernate as persistence layer (although this problem is purely SQL, I believe).
I've boiled down my problem to the following SQL statement:
SELECT TOP 2
this_.Id as Id36_0_,
this_.Name as Name36_0_,
ROW_NUMBER() OVER (ORDER BY this_.IsActive) as MyOrder
FROM Campsites this_
ORDER BY this_.IsActive /* a bit field */
This is part of the query that NH generates for retrieving a paged result set. The above statement gives me the following result:
Id36_0_ Name36_0_ MyOrder
9806 Camping A Cassagnau   1
8869 Camping a la ferme La Bergamotte 2
However, if I omit the ROW_NUMBER() OVER (ORDER BY this_.IsActive) - which is what NH generates for retrieving results on the first page - I get two completely different table entries in my result:
SELECT TOP 2
this_.Id as Id36_0_,
this_.Name as Name36_0_
/* ROW_NUMBER() OVER(ORDER BY this_.IsActive) as MyOrder */
FROM Campsites this_
ORDER BY this_.IsActive /* a bit field */
returns
Id36_0_ Name36_0_
22876 Centro Vacanze Pra delle Torri
22135 Molecaten Park Napoleon Hoeve
This completely confuses me and leads to a bug in our app where I get the same Campsite entry as the first element on the first AND the second page of our search.
Why does the same ORDER BY clause work differently inside the ROW_NUMBER OVER() expression?
ORDER BY this_.IsActive /* a bit field */
since that is a bit field it can only be 0 or 1...I assume you have many rows with this bit field being 0 or 1 ordering it by that doesn't make sense, what if 90% is active...you are not really ordering correctly in that case because you don't have a second ordering.
why don't you pick something that is unique...maybe his_.Name for example
or what about this?
ROW_NUMBER() OVER (ORDER BY this_.IsActive, this_.Name)
It's basically random in both instances because a bit field is bad for any ordering (as SQL Menace noted). They are separately evaluated by the DB Engine because they have nothing to do with each other.
Note:
The internal ORDER BY only applies to the ROW_NUMBER() value ordering.
Your output ORDER BY is only this_.IsActive
You expect the result to be ordered by Name too, but only have IsActive in the ORDER BY clause.
The nature of SELECT is set-based, so you should not rely on arbitrary (but seemingly correct) ordered results of your query if you do not explicitly define the order.