ID UserID LevelID
1 1 1
2 1 2
3 1 2
4 1 2
5 2 1
6 2 3
7 3 2
8 4 1
9 4 1
The query should return: LevelID: 1 (3 times) - the LevelID column that is most frequently repeated by different Users (UserID).
I have the following query:
SELECT LevelID, COUNT(LevelID) AS 'Occurrence'
FROM
(
SELECT DISTINCT * FROM
(
SELECT UserID, LevelID
FROM SampleTable
) cv
) levels
GROUP BY LevelID
ORDER BY 'Occurrence' DESC
Which returns:
LevelID Occurence
1 3
2 2
3 1
But it doesn't let me to add LIMIT 1; at the bottom to retrieve the first top row of the selection. What's wrong with the query?
There is no need for these several levels of nesting. Consider using aggregation, count(distinct ...), ordering the results and using a row-limiting clause to keep the top record only:
select top(1) levelID, count(distinct userID) cnt
from mytable
group by levelID
order by cnt desc
If you want to allow possible top ties, then use top (1) with ties instead of just top (1).
Related
I'm stuck with how to write SQL statements, so I would appreciate it if you could teach me.
Current status
items table
id
session_id
item_id
competition_id
1
1
2
1
2
1
3
1
2
1
2
1
2
1
2
1
2
1
5
2
3
1
7
2
4
1
4
2
5
1
5
2
want to
grouping by competition_id,
Count the same numbers in item_id,Extract the most common numbers and their numbers.
For example
If competition_id is 1,item_id → 2 ,and the number is 3
If competition_id is 2,item_id → 5 ,and the number is 2
If competition_id is 3,・・・
If competition_id is 4,・・・
environment
macOS BigSur
ruby 2.7.0
Rails 6.1.1
sqlite
In statistics, what you are asking for is the mode, the most common value.
You can use aggregation and row_number():
select ct.*
from (select competition_id, item_id, count(*) as cnt,
row_number() over (partition by competition_id order by count(*) desc) as seqnum
from t
group by competition_id, item_id
) ci
where seqnum = 1;
In the event that there are ties, this returns only one of the values, arbitrarily. If you want all modes when there are ties use rank() instead of row_number().
Consider the following table:
ID GroupId Rank
1 1 1
2 1 2
3 1 1
4 2 10
5 2 1
6 3 1
7 4 5
I need an sql (for MS-SQL) select query selecting a single Id for each group with the lowest rank. Each group needs to only return a single ID, even if there are two with the same rank (as 1 and 2 do in the above table). I've tried to select the min value, but the requirement that only one be returned, and the value to be returned is the ID column, is throwing me.
Does anyone know how to do this?
Use row_number():
select t.*
from (select t.*,
row_number() over (partition by groupid order by rank) as seqnum
from t
) t
where seqnum = 1;
I have a table with 2 columns MainID and ChildId.
My table:
MainID ChildId
-------------------------------
1 1
1 2
1 3
2 1
2 2
3 1
4 1
4 2
5 1
5 2
5 3
5 4
I want to select only last child Id for each MainId:
MainID ChildId
------------------------------
1 3
2 2
3 1
4 2
5 4
For this I am trying to use Top (1), but its only returning one row:
SELECT TOP (1)
MainId, ChildId
FROM
MYTABLE
ORDER BY
ChildId DESC
You need top 1 with ties
SELECT TOP (1) with ties MainId, ChildId
FROM MYTABLE
ORDER BY row_number() over (partition by MainId order by ChildId desc)
Also in that case you can not just order by ChildId because all values in top must be same. So you need row_number
Try this:
select MainId,
MAX(ChildId)
from MY_TABLE
group by MainId
If the last child is the one with the largest id, you can do:
SELECT TOP (1) WITH TIES MainId, ChildId
FROM MYTABLE
ORDER BY ROW_NUMBER() OVER (PARTITION BY MainId ORDER BY ChildId DESC);
There are other ways to accomplish this with subqueries -- and using window functions in ORDER BY is not initially intuitive.
I should note that this is SQL-Server-specific, but not because of ROW_NUMBER() in the ORDER BY clause. SQL Server supports TOP (n) WITH TIES, and there is not corresponding functionality in other databases.
I have the table below in an SQL database.
user rating
1 10
1 7
1 6
1 2
2 8
2 3
2 2
2 2
I would like to keep only the best two ratings by user to get:
user rating
1 10
1 7
2 8
2 3
What would be the SQL query to do that? I am not sure how to do it.
It will work
;with cte as
(select user,rating, row_number() over (partition by user order by rating desc) maxval
from yourtable)
select user,rating
from cte
where maxval in (1,2)
I have a table containing items in a priority order as such:
id priority
1 1
2 2
3 3
4 8
5 3
6 4
Currently I retrieve items (SQL Server) in priority order, although a random item when there are matching priorities using the following query:
select item
from table
order by priority, newid()
This will return
id priority
1 1
2 2
3 3
5 3
6 4
4 8
or
id priority
1 1
2 2
5 3
3 3
6 4
4 8
So it's approximately 50/50 traffic
I now have a requirement to only retrieve one row of the rows when there are two matching priorities, for example..
id priority
1 1
2 2
3 3
6 4
4 8
or
id priority
1 1
2 2
5 3
6 4
4 8
You can use ROW_NUMBER, presuming SQL-Server (because of NEWID):
WITH CTE AS
(
SELECT t.*, RN = ROW_NUMBER() OVER (PARTITION BY Priority
ORDER BY ID)
FROM dbo.table t
)
SELECT * FROM CTE WHERE RN = 1
If these are all columns you could also use this sql:
SELECT MIN(t.ID) AS ID, t.Priority
FROM dbo.table t
GROUP BY t.priority
Update "No, I need to be able to get a random row when two (or more) priorities match"
Then i have misunderstood your requirement. You can use ORDER BY NEWID:
WITH CTE AS
(
SELECT t.*, RN = ROW_NUMBER() OVER (PARTITION BY Priority
ORDER BY NEWID())
FROM dbo.table t
)
SELECT * FROM CTE WHERE RN = 1