how can I simulate the following sql query using linq. I just want to have a Row_Number column and use it's values in linq where clause.
With t As (
Select Row_Number() over ( Order by Id ) as 'RowId', * From Orders
)
Select * From t Where RowId between 1 and 10
I think what you're trying to do is just Skip/Take, for paging.
So basically:
var result = dataContext.Products.Skip(0).Take(10).ToList();
(Code is untested, written off the top of my head)
Related
I'm trying to write a Table-valued function in oracle, which contains a CTE.
I've been able to do it in SQL Server in this way:
ALTER FUNCTION [dbo].[region_parents]
(
#regionId INT
)
RETURNS TABLE
AS
RETURN
(
WITH cte AS
(
SELECT id, owner_region_id FROM regions WHERE id = #regionId
UNION ALL
SELECT r.id, r.owner_region_id
FROM cte INNER JOIN
regions r ON cte.owner_region_id = r.id
)
SELECT id
FROM cte
)
This is needed in order to call it in a cross apply:
SELECT *
FROM shops s
...
...
...
INNER JOIN locations l ON s.location_id = l.id
LEFT JOIN location_criteria lc ON lc.location_id = l.id
CROSS APPLY region_parents(l.region_id) r
In Oracle, I've tried to do it in this way, using User-Defined Datatypes:
CREATE OR REPLACE TYPE TABLE_RES_OBJ AS OBJECT (
id NUMBER
);
CREATE OR REPLACE TYPE TABLE_RES AS TABLE OF TABLE_RES_OBJ;
CREATE OR REPLACE FUNCTION region_parents (regionId IN INTEGER)
RETURN TABLE_RES
IS
cteresult TABLE_RES;
BEGIN
WITH cte(id, owner_region_id) AS
(
SELECT id AS id, owner_region_id AS owner_region_id FROM regions WHERE id = regionId
UNION ALL
SELECT r.id, r.owner_region_id
FROM cte INNER JOIN
regions r ON cte.owner_region_id = r.id
)
SELECT TABLE_RES(id)
BULK COLLECT INTO cteresult
FROM cte;
RETURN cteresult;
END;
/
The problem is that I obtain the following error:
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
I've also tried to achieve it in this way, without success.
Seems to be a simple distraction: "SELECT TABLE_RES(id)" should be "SELECT TABLE_RES_OBJ(id)".
It isn't anything to do with the CTE. You're trying to select a table object, not a simple object that is an element/row in that table. This:
SELECT TABLE_RES(id)
BULK COLLECT INTO cteresult
FROM cte;
should be:
SELECT TABLE_RES_OBJ(id)
BULK COLLECT INTO cteresult
FROM cte;
fiddle
I need to produce a systematic random sample of (approx) 2500 rows from (approx)230,000 rows with a unique auto generated number on each row.
Is this possible using Teradata SQL ast? (The Sample function produces a simple random sample.)
Thank you for your time.
When there's already a gapless unique row number:
select t.*
from mytable as t
cross join
( select random(1,2500) as rnd ) as dt -- random start row
where rownumber mod 2500 = rnd -- every 2500 rows
Otherwise ROW_NUMBER can be used to create it:
select t.*
from mytable as t
cross join
( select random(1,2500) as rnd ) as dt
qualify ROW_NUMBER() OVER (ORDER BY whatever_determines_your_order) mod 2500 = rnd
select rank() over(order by $primary_index_key), t1.*
FROM
(select * from $table_name
sample 2500) t1
Assistant would do that, and so would any other client.
Same approach can be used to generate winning Powerball numbers.
From your comment, I think that you cannot do it on the fly. You need to generate some table first that would contain Step# and step_value, for example:
[1,2500],[2,5000],...[x,x*2500]
Than you should join this table to your query and limit row numbers by the logic: rn = random_seed + step_value.
It will look like this:
select
from (
select t1.*
, row_number() over("ordering logic") as rn
from my_table
) as t1
, (select random(1,2500) as random_seed) as seed --so it will be generated only once
where exists (
select 1 from sampling_table as t2
where t1.rn = t2.step_value + seed.random_seed
)
I need to make a conversion from Oracle SQL to PostgreSQL.
select * from table1 inner join table2 on table1.id = table2.table1Id
where table1.col1 = 'TEST'
and rownum <=5
order by table2.col1
If I delete and rownum <=5 and put at the end limit 5, there are differences between the 2 dialects. In Oracle, first are selected the 5 elements, and after that, they are sorted by table2.col1 . In Postgres, first all the list is sorted, and AFTER there are selected the first 5 elements.
How can I obtain the same result in Postgres as in Oracle?
Thanks!
To get the behavior you desire, you can use a subquery like this:
SELECT * FROM (
SELECT table1.col1 as t1col1, table2.col1 as t2col1
FROM table1 INNER JOIN table2 ON table1.id = table2.table1Id
WHERE table1.col1 = 'TEST'
LIMIT 5
) AS sub
ORDER BY t2col1;
I named the columns there because in your example both tables had a col1.
Note however that without any ordering on the inner query, the selection of 5 rows you get will be purely random and subject to change.
Depending on the version you are using, PostgreSQL 8.4 and above have Window functions. Window function ROW_NUMBER() is capable of implementing the functionality of Oracle pseudo column rownum.
select row_number() over() as rownum,* from table1 inner join table2 on table1.id = table2.table1Id where table1.col1 = 'TEST' and rownum <=5 order by table2.col1;
Problem: I need write stored procedure(s) that will return result set of a single page of rows and the number of total rows.
Solution A: I create two stored procedures, one that returns a results set of a single page and another that returns a scalar -- total rows. The Explain Plan says the first sproc has a cost of 9 and the second has a cost of 3.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) AS RowNum, ...
) AS PageResult
WHERE RowNum >= #from
AND RowNum < #to
ORDER BY RowNum
SELECT COUNT(*)
FROM ...
Solution B: I put everything in a single sproc, by adding the same TotalRows number to every row in the result set. This solution feel hackish, but has a cost of 9 and only one sproc, so I'm inclined to use this solution.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) RowNum, COUNT(*) OVER () TotalRows,
WHERE RowNum >= from
AND RowNum < to
ORDER BY RowNum;
Is there a best-practice for pagination in Oracle? Which of the aforementioned solutions is most used in practice? Is any of them considered just plain wrong? Note that my DB is and will stay relatively small (less than 10GB).
I'm using Oracle 11g and the latest ODP.NET with VS2010 SP1 and Entity Framework 4.4. I need the final solution to work within the EF 4.4. I'm sure there are probably better methods out there for pagination in general, but I need them working with EF.
If you're already using analytics (ROW_NUMBER() OVER ...) then adding another analytic function on the same partitioning will add a negligible cost to the query.
On the other hand, there are many other ways to do pagination, one of them using rownum:
SELECT *
FROM (SELECT A.*, rownum rn
FROM (SELECT *
FROM your_table
ORDER BY col) A
WHERE rownum <= :Y)
WHERE rn >= :X
This method will be superior if you have an appropriate index on the ordering column. In this case, it might be more efficient to use two queries (one for the total number of rows, one for the result).
Both methods are appropriate but in general if you want both the number of rows and a pagination set then using analytics is more efficient because you only query the rows once.
In Oracle 12C you can use limit LIMIT and OFFSET for the pagination.
Example -
Suppose you have Table tab from which data needs to be fetched on the basis of DATE datatype column dt in descending order using pagination.
page_size:=5
select * from tab
order by dt desc
OFFSET nvl(page_no-1,1)*page_size ROWS FETCH NEXT page_size ROWS ONLY;
Explanation:
page_no=1
page_size=5
OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY - Fetch 1st 5 rows only
page_no=2
page_size=5
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY - Fetch next 5 rows
and so on.
Refrence Pages -
https://dba-presents.com/index.php/databases/oracle/31-new-pagination-method-in-oracle-12c-offset-fetch
https://oracle-base.com/articles/12c/row-limiting-clause-for-top-n-queries-12cr1#paging
This may help:
SELECT * FROM
( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num FROM emp)
WHERE Row_Num BETWEEN 5 and 10;
A clean way to organize your SQL code could be trough WITH statement.
The reduced version implements also total number of results and total pages count.
For example
WITH SELECTION AS (
SELECT FIELDA, FIELDB, FIELDC FROM TABLE),
NUMBERED AS (
SELECT
ROW_NUMBER() OVER (ORDER BY FIELDA) RN,
SELECTION.*
FROM SELECTION)
SELECT
(SELECT COUNT(*) FROM NUMBERED) TOTAL_ROWS,
NUMBERED.*
FROM NUMBERED
WHERE
RN BETWEEN ((:page_size*:page_number)-:page_size+1) AND (:page_size*:page_number)
This code gives you a paged resultset with two more fields:
TOTAL_ROWS with the total rows of your full SELECTION
RN the row number of the record
It requires 2 parameter: :page_size and :page_number to slice your SELECTION
Reduced Version
Selection implements already ROW_NUMBER() field
WITH SELECTION AS (
SELECT
ROW_NUMBER() OVER (ORDER BY FIELDA) RN,
FIELDA,
FIELDB,
FIELDC
FROM TABLE)
SELECT
:page_number PAGE_NUMBER,
CEIL((SELECT COUNT(*) FROM SELECTION ) / :page_size) TOTAL_PAGES,
:page_size PAGE_SIZE,
(SELECT COUNT(*) FROM SELECTION ) TOTAL_ROWS,
SELECTION.*
FROM SELECTION
WHERE
RN BETWEEN ((:page_size*:page_number)-:page_size+1) AND (:page_size*:page_number)
Try this:
select * from ( select * from "table" order by "column" desc ) where ROWNUM > 0 and ROWNUM <= 5;
I also faced a similar issue. I tried all the above solutions and none gave me a better performance. I have a table with millions of records and I need to display them on screen in pages of 20. I have done the below to solve the issue.
Add a new column ROW_NUMBER in the table.
Make the column as primary key or add a unique index on it.
Use the population program (in my case, Informatica), to populate the column with rownum.
Fetch Records from the table using between statement. (SELECT * FROM TABLE WHERE ROW_NUMBER BETWEEN LOWER_RANGE AND UPPER_RANGE).
This method is effective if we need to do an unconditional pagination fetch on a huge table.
Sorry, this one works with sorting:
SELECT * FROM (SELECT ROWNUM rnum,a.* FROM (SELECT * FROM "tabla" order by "column" asc) a) WHERE rnum BETWEEN "firstrange" AND "lastrange";
I have a complex query with group by and order by clause and I need a sorted row number (1...2...(n-1)...n) returned with every row. Using a ROWNUM (value is assigned to a row after it passes the predicate phase of the query but before the query does any sorting or aggregation) gives me a non-sorted list (4...567...123...45...). I cannot use application for counting and assigning numbers to each row.
Is there a reason that you can't just do
SELECT rownum, a.*
FROM (<<your complex query including GROUP BY and ORDER BY>>) a
You could do it as a subquery, so have:
select q.*, rownum from (select... group by etc..) q
That would probably work... don't know if there is anything better than that.
Can you use an in-line query? ie
SELECT cols, ROWNUM
FROM (your query)
Assuming that you're query is already ordered in the manner you desire and you just want a number to indicate what row in the order it is:
SELECT ROWNUM AS RowOrderNumber, Col1, Col2,Col3...
FROM (
[Your Original Query Here]
)
and replace "Colx" with the names of the columns in your query.
I also sometimes do something like:
SELECT * FROM
(SELECT X,Y FROM MY_TABLE WHERE Z=16 ORDER BY MY_DATE DESC)
WHERE ROWNUM=1
If you want to use ROWNUM to do anything more than limit the total number of rows returned in a query (e.g. AND ROWNUM < 10) you'll need to alias ROWNUM:
select *
(select rownum rn, a.* from
(<sorted query>) a))
where rn between 500 and 1000