Find the Range from a Table - sql

I have a table with the following values
id Level Threshold
1 1 5000
2 2 10000
3 3 15000
What i need to achieve is that when i pass 6000 , I need to get Level 1.
12000 Level 2 and 16000 Level 3?
6000 - Level 1
12000 - Level 2
16000 - Level 3
Can someone let me know how this can be achieved?

What I understood from your question is that when user will give 6000 then it should check which value is less than 6000 so it's 5000 and it's level is 1 same as when 12000 so it has two output as 5000 (level1) and 10000 (level2) but you need maximum one so it is 10000 (Level2). So according to this understanding the query is :
select max(LEVEL) from Table where Threshold< 6000;

How about an SQL question like this?
SELECT One.Level, One.Threshold
FROM
TableName AS One,
(SELECT MAX(Threshold) AS Maximum FROM TableName WHERE Threshold <= :value) AS Two
WHERE One.Threshold = Two.Maximum
Replace :value with 6000, 12000, 16000 or whatever value you are interested in. The inner query finds the maximum threshold that the value has reached. The outer query returns the level number for threshold.
Disclaimar: I have not tested this.

Try Below example, might be you want below one
create table #temp (id int, value int)
insert into #temp values (1, 6000)
insert into #temp values (2, 12000)
insert into #temp values (3, 15000)
insert into #temp values (4, 16000)
select * from #temp
select id, ceiling(convert(float,value)/6000) as level, value from #temp

Fiddle Demo
create table temp (id int, level int, Threshold int);
insert into temp values (1,1, 5000);
insert into temp values (2,2, 10000);
insert into temp values (3,3, 15000);
select max(LEVEL) from temp where Threshold<= 8000; (8000 or any other value)

Related

How to insert a record into a table - depending on the total requiredQty from another table?

I have this row in the database table:
ID requiredQty
1088 30
And another table:
ID orderLineID bookedInQty
3000 1088 10
3001 1088 10
dbfiddle: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=9ecd8c83fcda08453481ec6d0ce45947
Summary
Total booked in quantity is total of 20 and 10 remaining for that particular order-line.
Question
How can I create an if statement to insert a record into the 2nd table, not to exceed table 1 requiredQty: 30?
Example
If insert bookedInQty: 11 this means it exceeds 30 because there is an extra 1. If it exceeds, simply do nothing.
If to insert bookedInQty: 9 this does not exceeds 30 because the total now equals to 29. Then insert this record.
Note
Without creating any extra tables, I am trying to do it using an if statement.
This uses if to check if the sum of the bookedQty and the new value are lower then the required quantity. You can put the code in a stored procedure.
create table table1(
id int NOT NULL,
requiredQty int
);
create table table2(
id int NOT NULL,
orderLineId int,
bookedInQty int
);
insert into table1(id, requiredQty) VALUES (1088, 30);
insert into table2(id, orderLineId, bookedInQty)
VALUES
(3000, 1088, 10),
(3001, 1088, 10);
declare #sumQty int, #newQty int, #newOrderLineId int;
select #newOrderLineId = 1088, #newQty = 11; -- change #newQty to 10 or lower
select #sumQty = sum(bookedInQty) from table2 where orderLineId = #newOrderLineId
group by orderLineId;
-- I hardcoded the value of id, it should add 1 to the maximum value or use an identity column
if exists(select * from table1 where id = #newOrderLineId and requiredQty >= #sumQty + #newQty)
insert table2 (id, orderLineId, bookedInQty) values (3002, #newOrderLineId, #newQty);
select * from table1;
select * from table2;
Dbfiddle demo:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d800624279381f9bbd71cf51bbc5351a

What is output of this query and Why?

declare #table as table
(
id int identity(1,1), salary int
)
insert into #table values(1000)
insert into #table values(2000)
insert into #table values(5000)
insert into #table values(4000)
insert into #table values(1000)
insert into #table values(8000)
insert into #table values(9000)
insert into #table values(6000)
insert into #table values(1000)
insert into #table values(7000)
insert into #table values(3000)
select
A.salary
from
#table as A
where
(select count(*)
from #table B
where b.salary < A.salary) > 5
It will display the salary which is greater than 5000
In the query, you are self joining a table.
And You are counting number of records from inner table which are higher than current record of outer table.
So it will give you 5 records from table A which are higher than 5 records from inner query
Sub Query select count(*) from #table B where b.salary < A.salary will give you number of records which are less in salary than of table A
And So the result.
your query gonna return
5000
8000
9000
6000
7000
because as per your query it will check if a record is greater then 6 other records of the table or not.
as the inner query counting it for you.
if you remove all entries of 1000 the result will change to
8000
9000
because now only these two records are greater then 6 other records of the tables.

How to generate batch number in SQL Server

Any idea on how to generate batch numbers into a batch_number column in SQL Server table from 1 to 3 and repeat it again as shown below in the script?
Thanks in advance
Declare #mTestTable table
(
id int,
city varchar(50),
batch_number int
)
--Insert some sample data
Insert into #mTestTable values (1, 'London')
Insert into #mTestTable values (2, 'Karachi')
Insert into #mTestTable values (3, 'New York')
Insert into #mTestTable values (4, 'Melbourne')
Insert into #mTestTable values (5, 'Beijing')
Insert into #mTestTable values (6, 'Tokyo')
Insert into #mTestTable values (7, 'Moscow')
I need to generate batch number from 1 to 3 and repeat it again.
Id City Batch_Number
1 London 1
2 Karachi 2
3 New York 3
4 Melbourne 1
5 Beijing 2
6 Tokyo 3
7 Moscow 1
Use row_number() and some arithmetic:
with toupdate as (
select t.*, 1 + ((row_number() over (order by id) - 1) % 3) as new_batch_no
from testtable
)
update toupdate
set batch_number = new_batch_number;
update #mTestTable
set batch_number = (id-1) % 3 + 1
If the IDs won't be sequential, then one way to do it is using a cursor passing through it. Simply count the rows one by one and update the appropriate batch number.

Turn value into singular row

Current
Name Quantity
---------------
Stella 2
Jennifer 2
Greg 3
Requested result
Name Quantity
---------------
Stella 1
Stella 1
Jennifer 1
Jennifer 1
Greg 1
Greg 1
Greg 1
How should I do it?
declare #T table
(
Name varchar(50),
Sales int
)
insert into #T values
('Stella', '2'),
('Jennifer', '2'),
('Greg', '3')
If the maximum value in the quantity column is known to be less than 32,767, you can use Recursion to generate numbers and join the Numbers to achieve your result.
/*******************************************
Max Recursion Count in SQL Server is 32767
Limitation of 32767 Numbers!
******************************************/
;WITH Numbers (Number) AS
(
SELECT 1
UNION ALL
SELECT 1 + Number FROM Numbers WHERE Number < 100
)
SELECT m.Name,
Quantity = 1
FROM MyTable m
JOIN #numbers n ON m.Quantity <= n.Number
OPTION (MAXRECURSION 32767);
Using recursion and borrowing Michael Fredrickson's setup code:
declare #T table (
Name varchar(50),
Sales int
)
insert into #T values ('Stella', '2')
insert into #T values ('Jennifer', '2')
insert into #T values ('Greg', '3')
-- Recursive verion
;with People (Name, Sales) as
(
select Name, Sales
from #T
union all
select Name, Sales - 1
from People
where Sales - 1 > 0
)
select Name, 1 as Quantity
from People
option (maxrecursion 0) -- Recurse without limit
This seems to run faster on my box (5x faster than Michael Fredrickson's according to query plan, but with many more logical reads), not that it matters much.
You'll probably want to have a pre-populated numbers table to do this:
declare #T table (
Name varchar(50),
Sales int
)
declare #numbers table (
Number int
)
insert into #numbers values (1)
insert into #numbers values (2)
insert into #numbers values (3)
insert into #numbers values (4)
-- Etc... up to however many numbers is the max possible value for sales...
insert into #T values ('Stella', '2')
insert into #T values ('Jennifer', '2')
insert into #T values ('Greg', '3')
SELECT
t.Name,
1 AS Sales
FROM
#T t JOIN
#numbers n ON
t.Sales >= n.Number
ORDER BY t.Name
That's how you could do it, but I'm not sure on why you would want to do it.

SQL Query to return rows where a list of numbers is between start and end values

There is a table in Oracle with the columns:
id | start_number | end_number
---+--------------+------------
1 | 100 | 200
2 | 151 | 200
3 | 25 | 49
4 | 98 | 99
5 | 49 | 100
There is a list of numbers (50, 99, 150).
I want an sql statement that returns all the ids where any of the numbers in the list of numbers is found equal to or between the start_number and the end_number.
Using the above example; 1, 4 and 5 should be returned.
1 - 150 is between or equal to 100 and 200
2 - none of the numbers are between or equal to 151 and 200
3 - none of the numbers are between or equal to 25 and 49
4 - 99 is between or equal to 98 and 99
5 - 50 and 99 are between or equal to 49 and 100
drop table TEMP_TABLE;
create table TEMP_TABLE(
THE_ID number,
THE_START number,
THE_END number
);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (1, 100, 200);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (2, 151, 200);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (3, 25, 49);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (4, 98, 99);
insert into TEMP_TABLE(the_id, the_start, the_end) values (5, 49, 100);
The following is the solution I came up with based on the comments and answers below plus some additional research:
SELECT
*
from
TEMP_TABLE
where
EXISTS (select * from(
select column_value as id
from table(SYS.DBMS_DEBUG_VC2COLL(50,99,150))
)
where id
BETWEEN TEMP_TABLE.the_start AND TEMP_TABLE.the_end
)
This works too:
SELECT
*
from
TEMP_TABLE
where
EXISTS (select * from(
select column_value as id
from table(sys.ku$_vcnt(50,99,150))
)
where id
BETWEEN TEMP_TABLE.the_start AND TEMP_TABLE.the_end
)
Here is a full example:
create table #list (
number int
)
create table #table (
id int,
start_number int,
end_number int
)
insert into #list values(50)
insert into #list values(99)
insert into #list values(150)
insert into #table values(1,100,200)
insert into #table values(2,151,200)
insert into #table values(3,25,49)
insert into #table values(4,98,99)
insert into #table values(5,49,100)
select distinct a.* from #table a
inner join #list l --your list of numbers
on l.number between a.start_number and a.end_number
drop table #list
drop table #table
You'll simply need to remove the code about #table (create, insert and drop) and put your table in the select.
It partly depends on how your are storing your list of numbers. I'll assume that they're in another table for now, as even then you have many options.
SELECT
*
FROM
yourTable
WHERE
EXISTS (SELECT * FROM yourList WHERE number BETWEEN yourTable.start_number AND yourTable.end_number)
Or...
SELECT
*
FROM
yourTable
INNER JOIN
yourList
ON yourList.number BETWEEN yourTable.start_number AND yourTable.end_number
Both of those are the simplest expressions, and work well for small data sets. If your list of numbers is relatively small, and your original data is relatively large, however, this may not scale well. This is because both of the above scan the whole of yourTable and then check each record against yourList.
What may be preferable is to scan the list, and then attempt to use indexes to check against the original data. This would require you to be able to reverse the BETWEEN statement to yourTable.start_number BETWEEN x and y
This can only be done if you know the maximum gap between start_number and end_number.
SELECT
*
FROM
yourList
INNER JOIN
yourTable
ON yourTable.end_number >= yourList.number
AND yourTable.start_number <= yourList.number
AND yourTable.start_number >= yourList.number - max_gap
To achieve this I would store the value of max_gap in another table, and update it as the values in yourTable change.
You will want to create a temporary table to hold your numbers, if the numbers aren't already in one. Then it becomes relatively simple:
SELECT DISTINCT mt.ID FROM MyTable mt
INNER JOIN TempTable tt --your list of numbers
ON tt.number Between mt.start_number and mt.end_number
To create the table based on an array of passed values, you can use table definitions in your procedure. I'm light on Oracle syntax and don't have TOAD handy, but you should be able to get something like this to work:
CREATE OR REPLACE PROCEDURE FindIdsFromList
AS
DECLARE
TYPE NumberRecord IS RECORD (Number int NOT NULL)
TYPE NumberList IS TABLE OF NumberRecord;
NumberList myNumberList;
BEGIN
myNumberList := (50,99,150);
SELECT DISTINCT mt.ID FROM MyTable mt
INNER JOIN myNumberList nt --your list of numbers
ON nt.Number Between mt.start_number and mt.end_number
END