selecting the next set of top 30 records - sql-server

This is my query:
SELECT Top 30 *
FROM (SELECT *, Row_number() OVER( PARTITION BY EntityPicURL
ORDER BY FavoriteCount desc) AS RN
FROM TweetEntity
WHERE HashTag LIKE '%%23RIPOlgaSyahputra%') A
WHERE RN = 1
ORDER BY FavoriteCount desc , LastModifieddateTime desc
This will select the first 30 unique records of the column entitypicURl. Now that I want to select the next 30 records (31-60).
This is a sort of a query i used earlier but this returned many duplicate entries of entitypicURL.
select *
from (select *, row_no = row_number() over (order by FavoriteCount desc,
LastModifiedDateTime desc)
from TweetEntity
where HashTag like '%%23RIPOlgaSyahputra%') e
where e.row_no > 30 and e.row_no <=60
Now i want to combine the value of first query and include e.row_no>30 and e.row_no<60 from the second query.
It is not a duplicate. My confusion is just combining two queries because both has got row_numbers.

You can use nested CTEs like this:
;WITH CTE1 AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY EntityPicURL
ORDER BY FavoriteCount desc) AS RN
FROM TweetEntity
WHERE HashTag like '%%23RIPOlgaSyahputra%'
), CTE2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER FavoriteCount DESC,
LastModifiedDateTime DESC) AS row_no
FROM CTE1
WHERE RN = 1
)
SELECT *
FROM CTE2
WHERE row_no > 30 and row_no <=60
CTE2 will apply ROW_NUMBER on the filtered by RN = 1 result set of CTE1.

You can Use OFFSET to fetch records like this
you can select 30 records from below query
Select * FROM TweetEntity
ORDER BY FavoriteCount desc OFFSET 0 ROWS FETCH NEXT 30 ROWS ONLY
you can select next 30 records from below query
Select * FROM TweetEntity
ORDER BY FavoriteCount desc OFFSET 30 ROWS FETCH NEXT 30 ROWS ONLY
Note: OFFSET Will work on Sql server 2012+
Limitations in Using OFFSET-FETCH
ORDER BY is mandatory to use OFFSET and FETCH clause.
OFFSET clause is mandatory with FETCH. You can never use, ORDER BY …
FETCH.
TOP cannot be combined with OFFSET and FETCH in the same query
expression.
The OFFSET/FETCH rowcount expression can be any arithmetic, constant,
or parameter expression that will return an integer value. The
rowcount expression does not support scalar sub-queries.

Related

How to Remove Duplicate Statement

How to delete duplicate data row in SQL Server where there are not any unique value differences? I remain only one statement from my sales table (dbo.Sales)
ID DESCRIPTIONS QTY RATE AMOUNT
--------------------------------
1 APPLE 50 100 1000
1 APPLE 50 100 1000
1 APPLE 50 100 1000
1 APPLE 50 100 1000
We can try using a CTE here to arbitrarily delete all but one of the duplicates:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID, DESCRIPTIONS, QTY, RATE, AMOUNT
ORDER BY (SELECT NULL)) rn
FROM yourTable
)
DELETE
FROM cte
WHERE rn > 1;
You can delete like following.
DELETE A
FROM (SELECT Row_number()
OVER (
partition BY id, descriptions, qty, rate, amount
ORDER BY (SELECT 1)) AS rn
FROM table1) A
WHERE a.rn > 1
If you want to use CTE, you can try like following.
;WITH cte
AS (SELECT Row_number()
OVER(
partition BY id, descriptions, qty, rate, amount
ORDER BY (SELECT 1)) RN
FROM table1)
DELETE FROM cte
WHERE rn > 1
you can use this:
select distinct * into temp from tableName
delete from tableName
insert into tableName
select * from temp
drop table temp
I suggest to add a column like rn and feed it by row_number() over (Partition by ID, DESCRIPTIONS ,QTY, RATE, AMOUNT order by Id)
Now delete the data having rn not equal to 1
after completion drop that column... this is a one time solution if it is frequent that add a unique key in your table

SQL select the row with max value using row_number() or rank()

I have data of following kind:
RowId Name Value
1 s1 12
22 s1 3
13 s1 4
10 s2 14
22 s2 5
3 s2 100
I want to have the following output:
RowId Name Value
1 s1 12
3 s2 100
I am currently using temp tables to get this in two step. I have been trying to use row_number() and rank() functions but have not been successful.
Can someone please help me with syntax as I feel row_number() and rank() will make it cleaner?
Edit:
I changed the rowId to make it a general case
Edit:
I am open to ideas better than row_number() and rank() if there are any.
If you use rank() you can get multiple results when a name has more than 1 row with the same max value. If that is what you are wanting, then switch row_number() to rank() in the following examples.
For the highest value per name (top 1 per group), using row_number()
select sub.RowId, sub.Name, sub.Value
from (
select *
, rn = row_number() over (
partition by Name
order by Value desc
)
from t
) as sub
where sub.rn = 1
I can not say that there are any 'better' alternatives, but there are alternatives. Performance may vary.
cross apply version:
select distinct
x.RowId
, t.Name
, x.Value
from t
cross apply (
select top 1
*
from t as i
where i.Name = t.Name
order by i.Value desc
) as x;
top with ties using row_number() version:
select top 1 with ties
*
from t
order by
row_number() over (
partition by Name
order by Value desc
)
This inner join version has the same issue as using rank() instead of row_number() in that you can get multiple results for the same name if a name has more than one row with the same max value.
inner join version:
select t.*
from t
inner join (
select MaxValue = max(value), Name
from t
group by Name
) as m
on t.Name = m.Name
and t.Value = m.MaxValue;
If you really want to use ROW_NUMBER() you can do it this way:
With Cte As
(
Select *,
Row_Number() Over (Partition By Name Order By Value Desc) RN
From YourTable
)
Select RowId, Name, Value
From Cte
Where RN = 1;
Unless I'm missing something... Why use row_number() or rank?
select rowid, name, max(value) as value
from table
group by rowid, name

How to achieve pagination in SQL Server 2008 with like statement

My query for pagination result is
SELECT
*
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY Id DESC) AS RowNum,
*
FROM
My_Table) AS RowConstrainedResult
WHERE
(RowNum >= 1 AND RowNum <= 10)
ORDER BY
RowNum
This works fine. But when I try this for search result with like statement, it didn't work.
Search query
SELECT
*
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY Id DESC) AS RowNum,
*
FROM
My_Table) AS RowConstrainedResult
WHERE
column1 LIKE '%search%'
AND (RowNum >= 1 AND RowNum <= 10)
ORDER BY
RowNum
If first 10 rows don't contains search value, its return 0 results instead looking for full table. I can't use offset and fetch because it doesn't support in SQL Server 2008.
Any better way to use for pagination which work fine for like and normal in SQL Server 2008
Thanks
You're really close.. I'd use a CTE to filter, then select your 10 rows from it.
;WITH X AS
(
SELECT ROW_NUMBER() OVER (ORDER BY Id DESC) AS RowNum, *
FROM My_Table
WHERE column1 LIKE '%search%'
)
SELECT *
FROM X
WHERE RowNum BETWEEN 1 AND 10
ORDER BY RowNum
Depending on your situation, you may be able to simply get away with:
SELECT TOP 10 *, ROW_NUMBER() OVER (ORDER BY Id DESC) AS RowNum
FROM My_Table
WHERE column1 LIKE '%search%'
ORDER BY RowNum

SQL Server: How to select fist 10 records from table without using TOP keyword

There is a table which contains 50 records. I want to select first 10 records without using TOP keyword.
In SQL Server 2012+ you can use OFFSET ... FETCH
SELECT *
FROM YourTable
ORDER BY YourColumn ASC
OFFSET 0 ROWS
FETCH FIRST 10 ROWS ONLY
You can use ROW_NUMBER and Common Table Expression to query any range of data.
USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
FROM Sales.SalesOrderHeader
)
SELECT SalesOrderID, OrderDate, RowNumber
FROM OrderedOrders
WHERE RowNumber <= 10 -- other conditions: RowNumber between 50 and 60
Refere ROW NUMBER Here
Although it's probably the same thing internally, you can use
set rowcount 10
and then run the query.
I guess you can try something like this:
SELECT t.Id, t.Name FROM Table t
WHERE 10 > (SELECT count(*) FROM Table t2 WHERE t.id > t2.id)
You can use ROW_NUMBER. Let's say your table contains columns ID and Name. In that case you can use such query:
SELECT t.Id, t.Name
FROM (
SELECT ID, Name,
ROW_NUMBER() OVER (ORDER BY Id) AS RowNumber
FROM TableName
) t
WHERE RowNumber <= 10

Filter first then select page

How to first filter the result based on params then to apply where-between?
Some thing like
With Results as
(
Select colName,Title, Row_Number(Over...) as row from a table where colName=5
)
Select * from Results
where
row between #first and #last
But it does not works. I need to move my where colName=5 from with clause to outside then I got wrong data as It first get rows between #first n #last then search for colName=5.
Also I want count of Results.
Any idea?
You can use COUNT(*) OVER() to get the count of the unfiltered results
WITH cte as
(
select *,
ROW_NUMBER() over (order by name desc) AS RN,
count(*) over() AS [Count]
from master..spt_values
)
SELECT name, number,[Count]
FROM cte
WHERE RN BETWEEN 20 AND 24
Returns
name number Count
----------------------------------- ----------- -----------
VIEW 8278 2506
VIEW 8278 2506
view 2 2506
varchar 3 2506
varbinary 1 2506
This has performance implications though. You might want to just calculate the COUNT up front and cache it somewhere rather than recalculating it for every page request.
Your ROW_NUMBER syntax is incorrect. It should be this:
With Results as
(
SELECT colName, Title, ROW_NUMBER() OVER (ORDER BY ...) AS RN
FROM your_table
WHERE colName = 5
)
SELECT * FROM Results
WHERE rn BETWEEN #first AND #last
ORDER BY rn
See the documentation for more information.
I use approach very similar to Martin Smiths (currently selected answer) and at least in the tests I've made it gives better performance results.
; WITH cte as
(
select *,
ROW_NUMBER() over (order by name desc) AS RN
from master..spt_values
)
SELECT name, number, (SELECT COUNT(*) FROM cte) AS [Count]
FROM cte
WHERE RN BETWEEN 20 AND 24
Run this and his queries side by side and compare execution plans.

Resources