SQL Server query for top rows to select with condition - sql

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.

Related

How to group and pick only certain values based on a field using select query SQL

I have a table as follow
ID
ORDERNO
1
123
1
123
2
456
2
456
During every select query done via application using JDBC, only the grouped records based on ORDERNO should be picked.
That means, for example, during first select query only details related to ID = 1, but we cannot specify the ID number in where clause because we do not know how many number of IDs will be there in future. So the query should yield only one set of records; application will delete those records after picking, hence next select query will result in picking other set of records. How to achieve it?
You can use TOP WITH TIES for this
SELECT TOP (1) WITH TIES
t.ID,
t.ORDERNO
FROM YourTable t
ORDER BY
t.ID;
If you want to select and delete at the same time you could delete using an OUTPUT clause
WITH cte AS (
SELECT TOP (1) WITH TIES
t.ID,
t.ORDERNO
FROM YourTable t
ORDER BY
t.ID
)
DELETE cte
OUTPUT deleted.*;
As one option you could select on the MIN(ID) like:
SELECT *
FROM yourtable
WHERE ID = (SELECT MIN(ID) FROM yourtable);
You could also use window functions to do this:
SELECT ID, ORDERNO
FROM
(
SELECT ID, ORDERNO
DENSE_RANK() OVER (ORDER BY ID ASC) AS dr
FROM yourtable
)dt
WHERE dr = 1;
order your rows and select top n number of rows that you want :
select top (1) with ties ID, ORDERNO
from tablename
order by ID asc

query without duplicates SQL

I have query with duplicates. And now I need to build query without duplicates. I'm trying to do it, but my query need long time. My query with duplicates:
SELECT
c.*
FROM
Clients c
INNER JOIN
(
SELECT
iin,
COUNT(iin) AS countIIN
FROM
Clients
GROUP BY
iin
HAVING
COUNT(iin) > 1
) cc
ON c.IIN = cc.IIN
ORDER BY
c.last_name DESC
I need above anti-query.
You can use below query to find only unique record.
WITH CTE AS
(SELECT *, COUNT(IIN) OVER (PARTITION BY IIN) RECORDCOUNT FROM CLIENTS)
SELECT * FROM CTE WHERE RECORDCOUNT =1
make sure * should be replace in query with required column.
Also if you want to fetch unique record from duplicate list as well then you can choose below query
WITH CTE AS
(SELECT *, RECORD_NUMBER() OVER (PARTITION BY IIN ORDER BY IIN) RECORDCOUNT FROM CLIENTS)
SELECT * FROM CTE WHERE RECORDCOUNT =1
To find duplicates in SQL Row_Number() function is best option,
Please check following query
WITH [CTE NoDuplicates] AS
(
SELECT
RN = ROW_NUMBER() OVER (PARTITION BY iin ORDER BY c.last_name DESC),
*
FROM Clients
)
DELETE FROM [CTE DUPLICATE] WHERE RN = 1

Select Top 100 Groups

I have thousands of groups in a table, something like :
1..
1..
2..
2..
2..
2..
3..
3..
.
.
.
10000..
10000..
How can i make a select that give me the Top 3 groups each time.
I Want something like select Top 3 from rows , but it have to return the first three groups not the first three rows.
You can try this :
;with cte as (
select distinct groupId from mytable order by groupid
)
select * from mytable where TheGroupId in (select top 3 groupdid from cte)
You can use DENSE_RANK to assign a number to each group. All members of the same group will have the same number. Then in an outer query, select top 3 groups:
SELECT *
FROM (SELECT *, DENSE_RANK() OVER (ORDER BY id) AS rnk
FROM mytable ) t
WHERE t.rnk <= 3
The above query assumes that id is the column used to group records together.
SQL Fiddle Demo
Use Ranking function Row_Number() :
SELECT *
FROM (SELECT *,
Row_number()
OVER(
partition BY GroupId
ORDER BY GroupId) AS [rn]
FROM YourTable) t
WHERE rn <= 3
Check this MSDN doc for details of all ranking functions.
There is a sql TOP statement that does this
SELECT TOP number|percent column_name(s) FROM table_name;
a description of what it does and how it is used in alternative sql statements for example for mysql and ms access can be found here: http://www.w3schools.com/sql/sql_top.asp
My bad i misread your question, this will return the top rows not groups, could you explain what you are trying to do in more detail?
SELECT *
FROM
(SELECT *
,ROW_NUMBER() OVER (PARTITION BY [Group] ORDER BY [Group] ASC)rn
FROM TableName
)A
WHERE rn <= 3

Using DISTINCT and TOP in the same query

I want to use DISTINCT and TOP in the same query. I tried
SELECT DISTINCT TOP 10 * FROM TableA
but I still have a duplicate personID, so I tought to do:
SELECT DISTINCT (personID) TOP 10 * FROM TableA
But here the syntax is wrong. How do I do it correctly?
You're using a SELECT * which is pulling in all records. If you want to use a true DISTINCT only list out the column you want to receive distinct values of. If you have multiple columns then all those columns combined make up one distinct record.
SELECT distinct TOP 10 personID
FROM TableA
Note that without an ORDER BY this will return the first 10 records in no particular order. The results could be different each time you run the query.
You seem to want 10 random records for different persons. Try this:
select t.*
from (select t.*,
row_number() over (partition by personid order by (select NULL)) as seqnum
from t
) t
where seqnum = 1
In general, though, when using top you should also be using an order by to specify what you mean by "top".
It works simply if you use query like this:
SELECT DISTINCT TOP 2 name FROM [ATTENDANCE] ;
In the above query, name is the column_name and [ATTENDANCE] is the table_name.
You can also use WHERE with this to make filtering conditions.
select distinct personid from tablea sample 10
This works in teradata
Maybe you can do like this:
SELECT TOP 10 t.* FROM (SELECT distinct personID FROM TableA) t
Few options:
1:
SELECT TOP 10 personID
FROM (SELECT distinct personID FROM TableA)
2:
;with cte as
(SELECT distinct personID FROM TableA)
SELECT top 10 personID FROM cte
3:
;with cte as
(SELECT personID,row_count=row_number() over (partition by personID order by personID)
FROM TableA
) SELECT top 10 personID FROM cte where row_count=1
I see this is an old question, but I can suggest a more elegant solution:
SELECT personDetails.*
FROM
(
SELECT TOP (10)
personID
personID
FROM TableA
GROUP BY personID --> use this instead of distinct
) AS distinctIds
OUTER APPLY
(
SELECT TOP (1) * --> fetch only one result matching personID
FROM TableA
WHERE TableA.personId = distinctIds.personID
) AS personDetails
You can use GROUP BY instead of DISTINCT, and you can use OUTER APPLY with TOP(1) to fetch only one matching result.
The Matt Busche answer is correct based on the post title.
But if, as it seems from your code examples, your problem is to have all the record fields from the distinct top 10 personID, you can use that as a subquery:
SELECT TableA.*
FROM TableA
INNER JOIN (SELECT DISTINCT TOP 10 personID FROM TableA) AS B
ON TableA.ID = B.ID
SELECT DISTINCT ta.personid FROM (SELECT TOP 10 * FROM TableA) ta
ta is object of subquery and using ta object we can distinct the values
i fixed it i did
select distinct personid from (SELECT TOP 10 * FROM TableA)
If the goal is to select the top 1 record of every personID, then use
select * from TableA group by personid
Since you are doing a "group by", it will return every column, but will ignore (not display) any additional rows with the same personId

paginating table and getting row count

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.