paginating table and getting row count - sql

The query below fetches a subset of rows from a table starting at row 10 and ending at row 20. In addition, to save a query I need to return the total number of rows in the table. This is the best solution that I could think of. Are there any more efficient/elegant ways? In particular, I do not like the partition by 1 part.
select *
from (select count(*) over (partition by 1) as [count],
row_number() over (order by [Name],[Description]) as [row],
*
from [Products]) as t
where row between 10 and 20

If you don't like it, remove it!
select *
from (select count(*) over () as [count],
row_number() over (order by [Name],[Description]) as [row],
*
from [Products]) as t
where row between 10 and 20
However, that aside, the query isn't optimal. You should do the count the traditional way.
select *
from (select count(*) as [count]
from [Products]) X
cross join (
select row_number() over (order by [Name],[Description]) as [row],
*
from [Products]) as t
where row between 10 and 20
You can put both of these together and press Ctrl-M, then execute. The plans will look quite different.

Related

Select next 20 rows after top 10

I'm trying to select next 20 rows after top 10 rows.
select TOP 20 *
from memberform
where Row_Number over(10)
You need to use something like a CTE (Common Table Expression) and a ROW_NUMBER to define row numberings for your data set - then select from that numbered CTE for the set of rows you want:
;WITH PagingCte AS
(
SELECT
(list of columns),
RowNum = ROW_NUMBER() OVER (ORDER BY -some-column-of-yours-)
FROM
dbo.memberform
)
SELECT
(list of columns)
FROM
PagingCte
WHERE
RowNum BETWEEN 10 AND 29
In the inner ROW_NUMBER() window function, you need to define an ordering which defines how the rows are numbered (order by date, or by ID, or whatever makes sense for you).
Without an explicit ordering, there is no next 20 after the first 10 to be had..
do you mean offset clause ?
OFFSET excludes the first set of records.
OFFSET can only be used with an ORDER BY clause.
OFFSET with FETCH NEXT returns a defined window of records.
OFFSET with FETCH NEXT is great for building pagination support.
The general syntax to exclude first n records is:
SELECT column-names
FROM table-name
ORDER BY column-names
OFFSET n ROWS
Please refer to http://www.dofactory.com/sql/order-by-offset-fetch
WITH T AS
(
SELECT TOP 30 name,
row_number() OVER (ORDER BY id) AS RN
FROM memberform
ORDER BY id
)
SELECT
MAX(CASE WHEN RN <=10 THEN name END) AS Col1,
MAX(CASE WHEN RN > 10 THEN name END) AS Col2
FROM T
GROUP BY RN % 10

Get top N records grouped by another field

I have an Oracle table with ID, SUBJECT, and PAYLOAD (CLOB). I'd like to get a listing of the TOP 10 records who have the biggest PAYLOAD (LENGTH(PAYLOAD)) grouped by subject. So if I have 10 DISTINCT SUBJECT's in the table, the query should return 100 rows (top 10 per subject).
Use row_number():
select t.*
from (select t.*, row_number() over (partition by subject order by length(payload) desc) as seqnum
from table t
) t
where seqnum <= 10;

SQL Server query for top rows to select with condition

I want to skip first 5 records and then select 10 records
I have a column email in table user. Here I am trying to select top 10 unique rows from table user using this query
select DISTINCT TOP 10 email from user
Now I am trying to select top 10 unique rows from table skipping the first 5 records
select DISTINCT SKIP 5 TOP 10 email from user
which is not done and return error.. can anyone help me
SELECT A.NAME FROM
(SELECT distinct RANK() OVER(ORDER BY NAME) RNK,NAME FROM USERS) A
WHERE A.RNK>4 AND A.RNK<16
Using LIMIT will not guarantee you that you will get top rows with proper order.
If you use ANALYTIC functions, it will give you proper results.
SQL_LIVE_DEMO
Here is one way to do it. I like to use Common Table Expressions for some things like this because it makes the query easy to understand, although this isn't particularly complicated.
WITH CTE AS
(
Select Distinct Email From User
)
,
CTE1 AS
(
Select Email, ROW_NUMBER() over (ORDER BY Email) AS RowNumber
From CTE
)
Select Top 10 * From CTE1 Where RowNumber > 5
with t2 as
(
select t1.*,
row_number() over (order by id) rn
from
(select email, max(id) as id from [user] group by email) as t1
)
select * from t2 where rn between 5 and 10
How about this:
SELECT *
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY email) AS row
FROM user ) a
WHERE row > 5 and row <= 10
I think you are using SKIP incorrectly, it should be part of the ORDER BY clause.
SELECT DISTINCT TOP(10) Email FROM TableName WHERE Email not in (SELECT TOP(5) Email From TableName)
You can try this code, in this query fetch distinct 10 email ids skip 5 records as you say in this question.

Apply aggregate function on subset of rows

I have a table that I want to calculate the average of one column but only for the last 10 rows.
SELECT AVG(columnName) as avg FROM tableName
I cannot apply top directly since this query only returns one row. I need a way to get the latest 10 rows and do the average on them.
Try this:
SELECT AVG(columnName) FROM
(SELECT TOP 10 columnName FROM tableName ORDER BY ColumnWhichHoldsOrder DESC) A
select avg(columnName)
from (
select columnName,
row_number() over (order by some column desc) as rn
from tableName
) t
where rn <= 10;

SQL query query about selecting particular number of rows

For example -
SELECT * FROM user_names returns about 100 rows.
How would you query to get only row no.30 to row no.40?
Well with MySQL you would do it as follows:
SELECT * FROM user_names LIMIT 30,10
you can use row_number
with CTE_Table
as (SELECT id, ROW_NUMBER() OVER(ORDER BY id DESC) AS Row_Number
FROM dbo.a)
select * from CTE_Table
WHERE Row_Number BETWEEN 30 AND 40
Assuming SQL Server
SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY user_names.id) as RowNumber, *
from user_names) un
where un.RowNumber between 30 and 40
replace the ORDER BY clause with whatever you want to order by.