row with minimum value of a column - sql

Having this selection:
id IDSLOT N_UM
------------------------
1 1 6
2 6 2
3 2 1
4 4 1
5 5 1
6 8 1
7 3 1
8 7 1
9 9 1
10 10 0
I would like to get the row (only one) which has the minimun value of N_UM, in this case the row with id=10 (10 0).

select * from TABLE_NAME order by COLUMN_NAME limit 1

I'd try this:
SELECT TOP 1 *
FROM TABLE1
ORDER BY N_UM
(using SQL Server)

Try this -
select top 1 * from table where N_UM = (select min(N_UM) from table);

Use this sql query:
select id,IDSLOT,N_UM from table where N_UM = (select min(N_UM) from table));

Method 1:
SELECT top 1 *
FROM table
WHERE N_UM = (SELECT min(N_UM) FROM table);
Method 2:
SELECT *
FROM table
ORDER BY N_UM
LIMIT 1
A more general solution to this class of problem is as follows.
Method 3:
SELECT *
FROM table
WHERE N_UM IN (SELECT MIN(N_UM) FROM table);

Here is one approach
Create table #t (
id int,
IDSLOT int,
N_UM int
)
insert into #t ( id, idslot, n_um )
VALUES (1, 1, 6),
(2,6,2),
(3,2,1),
(4,4,1),
(5,5,1),
(6,8,1),
(7,3,1),
(8,7,1),
(9,9,1),
(10, 10, 0)
select Top 1 *
from #t
Where N_UM = ( select MIN(n_um) from #t )

select TOP 1 Col , COUNT(Col) as minCol from employee GROUP by Col
order by mindep asc

Related

How to arrange continuous serial number in to two or multiple column sequentially in sql server?

I want to print or display 1 to 10 or any max number in two column format using MS Sql-Server query.
Just like below attached screen shot image.
So please give any suggestion.
Using a couple of inline tallies would be way faster than a WHILE. This version will go up to 1000 integers (500 rows):
DECLARE #Start int = 1,
#End int = 99;
SELECT TOP(CONVERT(int,CEILING(((#End*1.) - #Start + 1)/2)))
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1)*2 + #Start AS Number1,
CASE WHEN (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1)*2 + #Start +1 <= #End THEN (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1)*2 + #Start +1 END AS Number2
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N1(N)
CROSS APPLY (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N2(N)
CROSS APPLY (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N3(N);
An alternative way that looks less messy with the CASE and TOP would be to use a couple of CTEs:
WITH Tally AS(
SELECT TOP(#End - #Start + 1)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 + #Start AS I
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N1(N)
CROSS APPLY (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N2(N)
CROSS APPLY (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N3(N)),
Numbers AS(
SELECT I AS Number1,
LEAD(I) OVER (ORDER BY I) AS Number2
FROM Tally)
SELECT Number1,
Number2
FROM Numbers
WHERE Number1 % 2 = #Start % 2;
I like to use recursive queries for this:
with cte (num1, num2) as (
select 1, 2
union all
select num1 + 2, num2 + 2 from cte where num2 < 10
)
select * from cte order by num1
You control the maximum number with the inequality condition in the recursive member of the cte.
If you need to generate more than 100 rows, you need to add option(maxrecursion 0) at the very end of the query.
Assuming you are starting with a table with one column, you can use:
select min(number), max(number)
from sample_data
group by floor( (number - 1) / 2);
Alternatively, set-based solution using window functions:
use tempdb
;with sample_data as (
select 1 as val union all
select 2 union all
select 3 union all
select 4 union all
select 5 union all
select 6 union all
select 7 union all
select 8 union all
select 9 union all
select 10
)
, sample_data_split as
(
select
val
, 2- row_number() over (order by val) % 2 as columnid
, NTILE((select count(*) / 2 from sample_data) ) over (order by val) groupid
from sample_data
)
the intermediate result of sample_data_split is:
val columnid groupid
1 1 1
2 2 1
3 1 2
4 2 2
5 1 3
6 2 3
7 1 4
8 2 4
9 1 5
10 2 5
and then to get the resultset into a desired format:
select
min(case when columnid = 1 then val end) as column1
, min(case when columnid = 2 then val end) as column2
from sample_data_split
group by groupid
column1 column2
1 2
3 4
5 6
7 8
9 10
Those CTEs can be merged into a single SELECT:
select
min(case when columnid = 1 then val end) as column1
, min(case when columnid = 2 then val end) as column2
from
(
select
val
, 2- row_number() over (order by val) % 2 as columnid
, NTILE((select count(*) / 2 from sample_data) ) over (order by val) groupid
from sample_data
) d
group by groupid
The positive side of a such approach, that it scales well and has no upper boundary on how much rows to be processed
So I got this solution on it as below...
declare #t table
(
id int identity(1,1),
Number_1 int,
Number_2 int
)
declare #min int=1
declare #max int=10
declare #a int=0;
declare #id int=0
while(#min<=#max)
begin
if(#a=0)
begin
insert into #t
select #min,null
set #a=1
end
else if(#a=1)
begin
select top 1 #id=id from #t order by id desc
update #t set Number_2=#min where id=#id
set #a=0
end
set #min=#min+1
end
select Number_1,Number_2 from #t

SQL Server : how to write the correct query?

This is my query
SELECT
ROW_NUMBER() OVER (ORDER BY [OtpInfoId] ASC ) AS RowNumber,
[OtpInfoId] ,
[OtpStatusId]
INTO
#TempTable
FROM
RequestOTP.Main.TbOtpStatusHistory
And this is part of the results:
RowNumber OtpInfoId OtpStatusId
----------------------------------
1 1 2
2 1 1
3 1 9
4 1 5
1 2 2
2 2 1
3 2 9
4 2 5
1 3 2
2 3 1
3 3 9
4 3 5
5 3 7
I want write a query to return what OtpInfoId have OtpStatusId with at least one state 7
In this example, the query should return this result:
RowNumber OtpInfoId OtpStatusId
----------------------------------
1 3 2
2 3 1
3 3 9
4 3 5
5 3 7
But I don't know how to write it.
You can use a correlated subquery with a WHERE EXIST clause.
SELECT
ROW_NUMBER() OVER (ORDER BY [OtpInfoId] ASC ) AS RowNumber ,
[OtpInfoId] ,
[OtpStatusId]
INTO #TempTable
FROM RequestOTP.Main.TbOtpStatusHistory osh
WHERE EXISTS (
SELECT 1
FROM RequestOTP.Main.TbOtpStatusHistory
WHERE OtpStatusId = 7 AND OtpInfoId = osh.OtpInfoId
)
One method is to use an EXISTS.
SELECT *
FROM (SELECT row_number() OVER (ORDER BY [OtpInfoId] ASC) RowNumber,
[OtpInfoId],
[OtpStatusId]
FROM [RequestOTP].[Main].[TbOtpStatusHistory]) x
WHERE EXISTS (SELECT *
FROM [RequestOTP].[Main].[TbOtpStatusHistory] y
WHERE y.[OtpInfoId] = x.[OtpInfoId]
AND y.[OtpStatusId] = 7)
INTO #TempTable;
Try this:
SELECT * FROM RequestOTP.Main.TbOtpStatusHistory
WHERE OtpInfoId IN (
SELECT OtpInfoId FROM RequestOTP.Main.TbOtpStatusHistory WHERE OtpStatusId = 7
)
INTO #TempTable;
This subquery returns all the OtpInfoId that have OtpStatusId = 7
Here is one approach:
SELECT
RowNumber,
OtpInfoId,
OtpStatusId
FROM
(
SELECT
ROW_NUMBER() OVER (PARTITION BY [OtpInfoId] ORDER BY OtpInfoId) AS RowNumber,
COUNT(CASE WHEN OtpStatusId = 7 THEN 1 END) OVER (PARTITION BY OtpInfoId) cnt
[OtpInfoId],
[OtpStatusId]
FROM RequestOTP.Main.TbOtpStatusHistory
) t
WHERE cnt > 0
INTO #TempTable;
Note that the row numbering in your expected is not clear, because there is no obvious column which provides that ordering. What is missing is a partition on the OtpInfoId, so I added one.
Please try following script to see if it satisfies your requirement.
create table RequestOTP.Main.TbOtpStatusHistory
(
OtpInfoId int,
OtpStatusId int
)
insert into RequestOTP.Main.TbOtpStatusHistory values
(1,2),(1,1),(1,9),(1,5),(2,2),(2,1),
(2,9),(2,5),(3,2),(3,1),(3,9),(3,5),
(3,7)
;with cte as
(
SELECT
ROW_NUMBER() OVER (partition by OtpInfoId ORDER BY [OtpInfoId] ASC ) AS RowNumber,
[OtpInfoId] ,
[OtpStatusId]
FROM RequestOTP.Main.TbOtpStatusHistory
)
select * from cte
where OtpInfoId in
(select OtpInfoId from RequestOTP.Main.TbOtpStatusHistory where OtpStatusId=7)
/*
RowNumber OtpInfoId OtpStatusId
-------------------- ----------- -----------
1 3 2
2 3 1
3 3 9
4 3 5
5 3 7
*/
Best Regards,
Rachel

T-SQL Select all combinations of ranges that meet aggregate criteria

Problem restated per comments
Say we have the following integer id's and counts...
id count
1 0
2 10
3 0
4 0
5 0
6 1
7 9
8 0
We also have a variable #id_range int.
Given a value for #id_range, how can we select all combinations of id ranges, without using while loops or cursors, that meet the following criteria?
1) No two ranges in a combination can overlap (min and max of each range are inclusive)
2) sum(count) for a combination of ranges must equal sum(count) of the initial data set (20 in this case)
3) Only include ranges where sum(count) > 0
The simplest case would be when #id_range = max(id) - min(id), or 7 given the above data. In this case, there's only one solution:
minId maxId count
---------------------
1 8 20
But if #id_range = 1 for example, there would be 4 possible solutions:
Solution 1:
minId maxId count
---------------------
1 2 10
5 6 1
7 8 9
Solution 2:
minId maxId count
---------------------
1 2 10
6 7 10
Solution 3:
minId maxId count
---------------------
2 3 10
5 6 1
7 8 9
Solution 4:
minId maxId count
---------------------
2 3 10
6 7 10
The end goal is to identify which solutions have the fewest number of ranges (solution # 2 and 4, in above example where #id_range = 1).
this solution does not list all possible combination but just try to get group it in smallest possible no of rows.
Hopefully it will cover all possible scenario
-- create the sample table
declare #sample table
(
id int,
[count] int
)
-- insert some sample data
insert into #sample select 1, 0
insert into #sample select 2, 10
insert into #sample select 3, 0
insert into #sample select 4, 0
insert into #sample select 5, 0
insert into #sample select 6, 1
insert into #sample select 7, 9
insert into #sample select 8, 0
-- the #id_range
declare #id_range int = 1
-- the query
; with
cte as
(
-- this cte identified those rows with count > 0 and group them together
-- sign(0) gives 0, sign(+value) gives 1
-- basically it is same as case when [count] > 0 then 1 else 0 end
select *,
grp = row_number() over (order by id)
- dense_rank() over(order by sign([count]), id)
from #sample
),
cte2 as
(
-- for each grp in cte, assign a sub group (grp2). each sub group
-- contains #id_range number of rows
select *,
grp2 = (row_number() over (partition by grp order by id) - 1)
/ (#id_range + 1)
from cte
where count > 0
)
select MinId = min(id),
MaxId = min(id) + #id_range,
[count] = sum(count)
from cte2
group by grp, grp2

How to get closest n rows for specific row in table?

I have a table foo with its primary key id and some other columns.
My goal is to find for instance rows with id=3 and id=4 and rows with id=6 and id=7 for row with id=5 - in case I would like to find 2 closest previous and next rows.
In case there is only one or no such rows (e.g. for id=2 there is only previous row) I would like to get only possible ones.
The problem is there can be some rows missing.
Is there a common practice to make such queries?
I would try the following:
SELECT * FROM table WHERE id > ? ORDER BY id ASC LIMIT 2
followed by
SELECT * FROM table WHERE id <= ? ORDER BY id DESC LIMIT 2
You may be able to combine the above into the following:
SELECT * FROM table WHERE id > ? ORDER BY id ASC LIMIT 2
UNION
SELECT * FROM table WHERE id <= ? ORDER BY id DESC LIMIT 2
I think this would fit your description.
Select * from table where id between #n-2 and #n+2 and id <> #n
One way is this:
with your_table(id) as(
select 1 union all
select 2 union all
select 4 union all
select 5 union all
select 10 union all
select 11 union all
select 12 union all
select 13 union all
select 14
)
select * from (
(select * from your_table where id <= 10 order by id desc limit 3+1)
union all
(select * from your_table where id > 10 order by id limit 3)
) t
order by id
(Here 10 is start point and 3 is n rows you want)
This is a possible solution by numbering all the records and fetching those where row number is 2 rows greater or lower than the selected ID.
create table foo(id int);
insert into foo values (1),(2),(4),(6),(7),(8),(11),(12);
-- using ID = 6
with rnum as
(
select id, row_number() over (order by id) rn
from foo
)
select *
from rnum
where rn >= (select rn from rnum where id = 6) - 2
and rn <= (select rn from rnum where id = 6) + 2;
id | rn
-: | -:
2 | 2
4 | 3
6 | 4
7 | 5
8 | 6
-- using ID = 2
with rnum as
(
select id, row_number() over (order by id) rn
from foo
)
select *
from rnum
where rn >= (select rn from rnum where id = 2) - 2
and rn <= (select rn from rnum where id = 2) + 2;
id | rn
-: | -:
1 | 1
2 | 2
4 | 3
6 | 4
dbfiddle here

Select randomly And Sort the records

I have a table which has ID,name and Level columns.I want to SELECT the records of the Table by this pattern :
First Select Them randomly and then sort those random records by level column.
for example : my sample table and records:
ID name Level
---------------------------------
1 red-book 1
2 blue-pen 10
3 black-board 12
4 balck-Book 1
5 white-book 1
6 red-pen 10
7 green-pen 10
And the result should be something like this :
ID name level
------------------------------------------
3 black-board 12
6 red-pen 10
2 blue-pen 10
7 green-pen 10
4 balck-Book 1
1 red-book 1
5 white-book 1
I've also used
SELECT * FROM MyTable ORDER BY NEWID(),Level DESC
And
SELECT * FROM
(SELECT * FROM MyTable ORDERBY NEWID())As TempTbl
ORDER BY Level DESC
And
CREATE TABLE #MyTempTable (ID INT,name Nvarchar(256),Levels INT)
INSERT INTO #MyTempTable SELECT * FROM MyTable ORDER BY NEWID()
SELECT * FROM #MyTempTable ORDER BY Levels DESC
SELECT ID,name,level
FROM sample
ORDER BY level DESC,NEWID()