I'm using SQL Server management studio 2008 and use TOP to select some data from DB.
SELECT
TOP 3 Name, Company, ta_Content, Email, Writedate
FROM dbo.ta_CONTACT
WHERE Name in ('David', 'Filo', 'Rain', 'Cone', 'Source', 'Tailor', 'Fier', 'Venesse')
ORDER BY Writedate;
So by using TOP 3, I can collect top 3 data from 8 given data. But What I want to do is selecting 5-7th data from the given 8 data.
I may use ROW_NUMBER() but I want to use TOP logic by using NOT IN. But I'm not sure where to put NOT IN logic to show 5-7th data only.
Try this query:
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Writedate ASC) AS rownumber,
Name, Company, ta_Content, Email, Writedate
FROM dbo.ta_CONTACT
) AS t
WHERE rownumber >= 5 AND rownumber <= 7
Try this query.It is not right way.
select TOP 2 Name, Company, ta_Content, Email, Writedate from (
SELECT TOP 3 Name, Company, ta_Content, Email, Writedate FROM dbo.ta_CONTACT
WHERE Name in ('David', 'Filo', 'Rain', 'Cone', 'Source', 'Tailor', 'Fier', 'Venesse')
ORDER BY Writedate desc)a ORDER BY Writedate
Using TOP (3) and filter out the row 1 - 4, then you can get 5 - 7 records
SELECT TOP (3)
*
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY Writedate) Seq,
Name, Company, ta_Content, Email, Writedate
FROM dbo.ta_CONTACT
WHERE
-- The search criteria must be inside the inner select statement
Name in
('David', 'Filo', 'Rain', 'Cone', 'Source', 'Tailor', 'Fier', 'Venesse')
) filtered
WHERE
Seq >= 5
-- If you do not need the TOP statement just use below condition
-- Seq BETWEEN 5 AND 7
Related
I have a table (NerdsTable) with some of this data:
-------------+-----------+----------------
id name school
-------------+-----------+----------------
1 Joe ODU
2 Mike VCU
3 Ane ODU
4 Trevor VT
5 Cools VCU
When I run the following query
SELECT id, name, LEAD(id) OVER (ORDER BY id) as next_id
FROM dbo.NerdsTable where school = 'ODU';
I get these results:
[id=1,name=Joe,nextid=3]
[id=3,name=Ane,nextid=NULL]
I want to write a query that does not need the static check for
where school = 'odu'
but gives back the same results as above. In another words, I want to select all results in the database, and have them grouped correctly as if i went through individually and ran queries for:
SELECT id, name, LEAD(id) OVER (ORDER BY id) as next_id FROM dbo.NerdsTable where school = 'ODU';
SELECT id, name, LEAD(id) OVER (ORDER BY id) as next_id FROM dbo.NerdsTable where school = 'VCU';
SELECT id, name, LEAD(id) OVER (ORDER BY id) as next_id FROM dbo.NerdsTable where school = 'VT';
Here is the output I am hoping to see:
[id=1,name=Joe,nextid=3]
[id=3,name=Ane,nextid=NULL]
[id=2,name=Mike,nextid=5]
[id=5,name=Cools,nextid=NULL]
[id=4,name=Trevor,nextid=NULL]
Here is what I have tried, but am failing miserably:
SELECT id, name,
LEAD(id) OVER (ORDER BY id) as next_id
FROM dbo.NerdsTable
ORDER BY school;
-- Problem, as this does not sort by the id. I need the lowest id first for the group
SELECT id, name,
LEAD(id) OVER (ORDER BY id) as next_id
FROM dbo.NerdsTable
ORDER BY id, school;
-- Sorts by id, but the grouping is not correct, thus next_id is wrong
I then looked on the Microsoft doc site for aggregate functions, but do not see how i can use any to group my results correctly. I tried to use GROUPING_ID, as follows:
SELECT id, GROUPING_ID(name),
LEAD(id) OVER (ORDER BY id) as next_id
FROM dbo.NerdsTable
group by school;
But I get an error:
is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
Any idea as to what I am missing here?
From your desired output it looks like you are just trying to order the records by school. You can do that like this:
SELECT id, name
FROM dbo.NerdsTable
ORDER BY school ASC, id ASC
I don't know what next ID is supposed to mean.
create table schools (id int, name varchar(50), school varchar(3))
insert into schools values (1, 'Joe', 'ODU'), (2, 'Mike', 'VCU'), (3, 'Ane',
'ODU'), (4, 'Trevor', 'VT'), (5, 'Cools', 'VCU'), (6, 'Sarah', 'VCU')
select n.id, n.name, min(g.id) nextid
from schools n
left join
(
select id, school
from schools
) g on g.school = n.school and g.id > n.id
group by n.id, n.name
drop table schools
Is it possible to do the following for count >=3,4,5,6,7,8 etc.
rather than repeating the entire code for each count category
Insert into OnePlus (SELECT DISTINCT Id, Name, COUNT(DISTINCT StartDate) AS OnePlusDays
FROM DataTable
HAVING OnePlusDays >= 1
GROUP BY Id, Name)
Insert into TwoPlus (SELECT DISTINCT Id, Name, COUNT(DISTINCT StartDate) AS TwoPlusDays
FROM DataTable
HAVING TwoPlusDays >= 2
GROUP BY Id, Name)
Finally
SELECT Id, Name, "1+" AS Categories
FROM OnePlus
UNION
SELECT Id, Name, "2+" AS Categories
FROM TwoPlus
You mention only sql in the tags. Depending on MySql or SQL Server, you may need to change the Cast/Convert and Concatenation. But this query may help. You really don't need to put a Distinct on top a group by, the fact that you are grouping by, means only distinct values and their counts will be fetched.
Of course, the table OnePlus, is really what you call Categories.
Insert into OnePlus
SELECT Id, Name, convert(varchar(10), COUNT(DISTINCT StartDate) ) + "+" AS Categories
FROM DataTable
GROUP BY Id, Name
In T-SQL you can write as:
SELECT Id,
NAME , -- make sure you write case statement in desc order
CASE WHEN PlusDays > = 2 THEN '2+'
WHEN PlusDays > = 1 THEN '1+' END AS Categories
FROM
(
SELECT DISTINCT Id, Name, COUNT(DISTINCT StartDate) PlusDays
FROM #DataTable
GROUP BY Id, Name
) AS T
ORDER BY Id asc
I have a code where I need to pull 400 random employees from this list of over 60,000. THere are 8 different job groupings, I need a certain number of each from each grouping. So of the total 400 random samples I need that 400 needs to consist of specific numbers from each of the 8 groups. This is the code so far:
SELECT TOP (400) Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
FROM dbo.v_TMS_employee_HR
ORDER BY NEWID()
IE: Of the 400 random records returned: Group 1 needs to have 45, Group 2 needs 50, Group 3 needs 35, Group 4, needs 25, Group 5 needs 100, Group 6 needs 5, Group 7 needs 70 and Group 8 needs 70.
And each group is made up of 1-4 different job codes.
If it's just 8 groups you can have 8 separate queries (1 for each group) with their own TOP number and then UNION them all together.
Something like this (You will need to set the correct record amounts to get for each group and correct group codes):
SELECT * FROM
(SELECT TOP (100) Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
FROM dbo.v_TMS_employee_HR
WHERE Job_Group_Code=1
ORDER BY NEWID())
UNION
...................
UNION
...................
...................
UNION
SELECT * FROM (
SELECT TOP (10) Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
FROM dbo.v_TMS_employee_HR
WHERE Job_Group_Code=8
ORDER BY NEWID())
Since you clarified that there are several job_group_codes in a group you will need to use WHERE Job_Group_Code IN (1,2,3) instead.
If you have just 8 group and it's one time thing, please try #PM 77-1 suggested. However, I would use UNION ALL instead UNION.
If you have more group or number of records selected from each group are different, you may try the following way
DECLARE #GroupSelect TABLE (Job_Group_Code INT, NumberOfRecord INT)
INSERT INTO #GroupSelect VALUES (1 ,45), (2 ,50) , .... -- List all your group and number of records your want select from them
;WITH tbl AS (
SELECT Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
, ROW_NUMBER() OVER (PARTITION BY Job_Group_Code ORDER BY NEWID()) as RowNo
FROM dbo.v_TMS_employee_HR
)
, numbers (
-- if you don't have number table, you may use this.
select number + 1 as number from master..spt_values WHERE type = 'P'
)
SELECT t.*
from tbl t
INNER JOIN #GroupSelect sg
ON sg.Job_Group_Code = t.Job_Group_Code
INNER JOIN numbers n
ON sg.NumberOfRecord >= n.number
WHERE n.number = t.RowNo
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.
I have a web site that collects high scores for a game - the sidebar shows the latest 10 scores (not necessarily the highest, just the latest 10). However, since a user can play multiple games quickly, they can dominate the latest 10 list. How can I write an SQL squery to show the last 10 scores but limit it to one per user?
SELECT username, max(score)
FROM Sometable
GROUP BY username
ORDER BY Max(score) DESC
and from that, select the top X depending on your db platform. select top(10) in ms-sql 2005+
edit
sorry, I see that you want things ordered by date.
Here's a working query with ms-sql 2005.
;
WITH CTE AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY username ORDER BY dateadded DESC) AS 'RowNo',
username, score, dateadded FROM SomeTable
)
SELECT username, score, dateadded FROM CTE
WHERE RowNo = 1
Group by user... and either select the Max(Score), Max([Submission Date]) or whatever.
In SQL Server, you could use the RANK() OVER() with appropriate PARTITION and GROUP BY, but what platform are you using?
In the interest of providing another point of view you could just add a field "max score" to your user table and then use a simple query with an order by to get the top 10.
Your update will need to check if the new score if higher then the current max score.
It does have the advantage of querying a table that will most probably have less rows then your score table.
Anyway, just another option to consider.
SELECT s2.*
FROM
(SELECT user_id, MAX(action_time) AS max_time
FROM scores s1 GROUP_BY user_id
ORDER BY MAX(action_time) DESC LIMIT 10)s1
INNER JOIN scores s2 ON (s2.user_id = s1.user_id AND s2.action_time = s1.max_time)
This is Mysql syntax, for SQL server you need to use SELECT TOP 10 ... instead of LIMIT 10.
Here is a working example that I built on SQL Server 2008
WITH MyTable AS
(
SELECT 1 as UserId, 10 as Score UNION ALL
SELECT 1 as UserId, 11 as Score UNION ALL
SELECT 1 as UserId, 12 as Score UNION ALL
SELECT 2 as UserId, 13 as Score UNION ALL
SELECT 2 as UserId, 14 as Score UNION ALL
SELECT 3 as UserId, 15 as Score UNION ALL
SELECT 3 as UserId, 16 as Score UNION ALL
SELECT 3 as UserId, 17 as Score UNION ALL
SELECT 4 as UserId, 18 as Score UNION ALL
SELECT 4 as UserId, 19 as Score UNION ALL
SELECT 5 as UserId, 20 as Score UNION ALL
SELECT 6 as UserId, 21 as Score UNION ALL
SELECT 7 as UserId, 22 as Score UNION ALL
SELECT 7 as UserId, 23 as Score UNION ALL
SELECT 7 as UserId, 24 as Score UNION ALL
SELECT 8 as UserId, 25 as Score UNION ALL
SELECT 8 as UserId, 26 as Score UNION ALL
SELECT 9 as UserId, 26 as Score UNION ALL
SELECT 10 as UserId, 20 as Score
),
MyTableNew AS
(
SELECT Row_Number() OVER (Order By UserId) Sequence, *
FROM MyTable
),
RankedUsers AS
(
SELECT *, Row_Number() OVER (Partition By UserId ORDER BY Sequence DESC) Ranks
FROM MyTableNew
)
SELECT *
FROM MyTableNew
WHERE Sequence IN
(
SELECT TOP 5 Sequence
FROM RankedUsers
WHERE Ranks = 1
ORDER BY Sequence DESC
)