How to select top 3 maximum values from SQL Server column - sql-server

I have values in SQL Server derived column sorted as descending i.e.
id Count OR id Count OR id Count
1 4 1 5 1 11
2 4 2 2 2 1
3 4 3 1 3 1
4 4 4 1 4 1
5 4 5 1 5 1
Now I want to select top 3 maximum values. How can I select so that query returns consistent result every time.
For example if values of Count are same which id's should be returned as top 3 maximums, similarly if 3rd value is matched with other values and if 2nd value is matched with other values then which id's should be returned by the query. And the result should be consistent every time I execute the query.

The with ties argument of the top function will return all the of the rows which match the top values:
select top (3) with ties id, count from table1
order by count desc
Alternatively, if you wanted to return 3 values only, but make sure they are always the same 3 values, then you will need to use something else as a tie-breaker. In this case, it looks like your id column could be unique.
select top (3) id, count from table1
order by count desc, id

Related

Count number of rows for each id to create a new column

ID
value
1
4
1
5
3
4
2
10
I want to add another column called count, that has for each id the number of observations.
Transformed table
id
value
count
1
4
2
1
5
2
3
4
1
2
10
1
You can use the OVER() clause to aggregate.
SELECT
ID,
value,
[count] = COUNT(*) OVER (PARTITION BY ID)
FROM dbo.TableName;

Classifying rows into a grouping column that shows the data is related to prior rows

I have a set of data that I want to classify into groups based on a prior record id existing on the newer rows. The initial record of the group has a prior sequence id = 0.
The data is as follows:
customer id
sequence id
prior_sequence id
1
1
0
1
2
1
1
3
2
2
4
0
2
5
4
2
6
0
2
7
6
Ideally, I would like to create the following grouping column and yield the following results:
customer id
sequence id
prior sequence id
grouping
1
1
0
1
1
2
1
1
1
3
2
1
2
4
0
2
2
5
4
2
2
6
0
3
2
7
6
3
I've attempted to utilize island gap logic utilizing the ROW_NUMBER() function. However, I have been unsuccessful in doing so. I suspect the need here is more along the lines of a recursive CTE, which I am attempting at the moment.
I agree that a recursive CTE will do the job. Something like:
WITH reccte AS
(
/*query that determines starting point for recursion
*
* In this case we want all records with no prior_sequence_id
*/
SELECT
customer_id,
sequence_id,
prior_sequence_id,
/*establish grouping*/
ROW_NUMBER() OVER (ORDER BY sequence_id) as grouping
FROM yourtable
WHERE prior_sequence_id = 0
UNION
/*join the recursive CTe back to the table and iterate*/
SELECT
yourtable.customer_id,
yourtable.sequence_id,
yourtable.prior_sequence_id,
reccte.grouping
FROM reccte
INNER JOIN yourtable ON reccte.sequence_id = yourtable.prior_sequence_id
)
SELECT * FROM reccte;
It looks like you could use a simple correlated query, at least given your sample data:
select *, (
select Sum(Iif(prior_sequence_id = 0, 1, 0))
from t t2
where t2.sequence_id <= t.sequence_id
) Grouping
from t;
See Example Fiddle

Move a specific column for every rows of a group from a result set into a single row

I tried using pivot in SQL Server, but I'm just going in circles with no good results.
I have this result set that could vary in number of records:
ForeignID
Name
Value
1
A
1
1
B
2
1
C
3
2
D
4
How can I do a SELECT to get this for all rows with ForeignID of 1:
ForeignID
A
B
C
1
1
2
3

SQL Server sum column base on id

I have table and I want result like this:
id ItemId Quantity Sum
1 1 2 2
2 1 1 3
3 1 1 4
4 2 3 3
4 2 1 4
5 3 6 6
where id is primary key and ItemId is foreign key and Quantity is integer column.
I want that "sum" column sum quantity base on itemId.
I used group by but it does not give me what I want. With group by
I get this result:
id ItemId Quantity Sum
1 1 2 4
2 1 1 4
3 1 1 4
. . . .
. . . .
The "sum" column is same for all related rows.
I also used this code:
select it1.id, it1.ItemId, it1.Quantity ,
(select sum(it2.Quantity) from InventoryTransactions it2 where it2.ItemId = it1.ItemId and it2.id <= it1.Id) as Sum
from InventoryTransactions it1
order by it1.ItemId , it1.Id
This code gives me what I want but it takes too long for a large number of records, for example for one million records. It takes more than two minute to execute
What is the best way?
In sql server >= 2012 you can do a rolling sum easier
select it1.id, it1.ItemId, it1.Quantity,
sum(Quantity) over(partition by itemid order by Id rows unbounded preceding) as Sum
from InventoryTransactions it1
order by it1.ItemId , it1.Id

Get first value above current (stored procedure)

Currently I'm working on a stored procedure to update the sort order of a table. The idea is to make sure that the correct rows are swapped.
INPUT: ToMoveID INT, Up BIT (1 up, 0 down)
SERVER: MSSQL 2012
example to use:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 2 Yes
4 NULL No
5 3 Yes
The idea is to put the row with ID 5 higher, the ID of 3 is unkown at this point. How Can i get the ID of the row with te first sortorder higher as the current?
Sample values: TomoveID = 5, Up = 1
After sorting the result shoud be:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 3 Yes
4 NULL No
5 2 Yes
Thanks in advance
You can search for a row with the biggest SortOrder that is less than SortOrder of ID 5 row in this way:
SELECT TOP 1
tbl.ID
FROM YourTable tbl
WHERE tbl.SortOrder < (SELECT SortOrder FROM YourTable tbl2 WHERE tbl2.ID = 5)
ORDER BY
tbl.SortOrder DESC

Resources