Random Function behavior in SELECT query in SQL Server - sql

I have a written a random function dbo.UDF_Q_RandomNumber() that generates a floating type random number between 0 and 1.
DECLARE #upper = 10
DECLARE #lower = 1
SELECT
ROUND(CAST((#lower + (#upper - #lower) * dbo.UDF_Q_RandomNumber()) AS INT), 0)
The above code generates a random number between 1 and 10.
Now I created a temporary table #tempTable with 10 rows in it with columns Id and Number.
Id Number
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
SQL query:
CREATE TABLE #tempTable(Id INT, Number INT)
INSERT INTO #tempTable VALUES (1,1)
INSERT INTO #tempTable VALUES (2,2)
INSERT INTO #tempTable VALUES (3,3)
INSERT INTO #tempTable VALUES (4,4)
INSERT INTO #tempTable VALUES (5,5)
INSERT INTO #tempTable VALUES (6,6)
INSERT INTO #tempTable VALUES (7,7)
INSERT INTO #tempTable VALUES (8,8)
INSERT INTO #tempTable VALUES (9,9)
INSERT INTO #tempTable VALUES (10,10)
DECLARE #maxCount INT;
SELECT #maxCount= COUNT(1) FROM #tempTable
SELECT * FROM #tempTable
SELECT Number
FROM #tempTable
WHERE Id = ROUND(CAST((1+(#maxCount-1)*dbo.UDF_Q_RandomNumber())AS INT),0)
DROP TABLE #tempTable
Here the query
SELECT Number
FROM #tempTable
WHERE Id = ROUND(CAST((1+(#maxCount-1)*dbo.UDF_Q_RandomNumber()) AS INT), 0)
Sometimes it returns 2 rows and sometimes null which should not come as Id selected is between 1 and 10 (the rows in temptable) and every Id has value too.
Please help .

Without seeing the function, it's hard to say, but I suspect your function is non-deterministic, so it gets interpreted for each row of the table.
If you use rand() it only returns one row
SELECT Number FROM #tempTable WHERE Id= ROUND(CAST((1+(#maxCount-1)*rand())AS INT),0)
Alternatively, if you just want a random #n rows...
select top (#n) * from #tempTable order by newid()

Related

Find missing numbers in a sequence in MS SQL

Say i have a table with an integer column Id. I need to find the missing numbers in a sequence with a maximum returned amount.
If the table is empty and i'm asking for 10, it should return the numbers 1-10.
If the table has 1-5 and i'm asking for 10, it should return the numbers 6,7,8,9,10,11,12,13,14,15.
If the table has 1,2,4,6,9 and im asking for 10, it should return the numbers 3,5,7,8,10,11,12,13,14,15
How can i achive this in one single query using MS SQL?
Thanks in advance!
Try this:
If you need to get more numbers, just increase the WHERE Number<=100.
DECLARE #Tab1 TABLE (ID INT)
INSERT INTO #Tab1 VALUES(1)
INSERT INTO #Tab1 VALUES(3)
INSERT INTO #Tab1 VALUES(5)
INSERT INTO #Tab1 VALUES(7)
INSERT INTO #Tab1 VALUES(9)
;WITH CTE AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number + 1 FROM CTE
WHERE Number<=100
)
SELECT TOP 5 *
FROM CTE
WHERE Number NOT IN(SELECT ID FROM #Tab1)
ORDER BY Number
OPTION (maxrecursion 0);
Existing values:
Number
1
3
5
7
9
OutPut:
Number
2
4
6
8
10
Hope this helps you.
This should work
There are also a system table with numbers
declare #T table (i int primary key);
insert into #T values (1), (2), (4), (6), (9);
declare #count int = 10;
declare #size int = (select count(*) from #T);
with cte as
( select 1 as num
union all
select num + 1
from cte
where num + 1 <= (#count + #size)
)
select top (#count) cte.num
from cte
left join #T t
on t.i = cte.num
where t.i is null
order by cte.num
option ( MaxRecursion 0 );

Adding total row and Increasing quality for an sql query based on multiple parameters

I have a table in Microsoft Sql Server 2008 like:
id name timelong
1 Eray 2
1 Jack 1
1 Ali 7
1 john 3
1 Roby 5
1 Mike 4
1 Josh 11
What I want to do is to select data based on user multi-selectable parameters. Think that there are 4 checkboxes: 0-3,4-6,7-9,10-12 and users can select more than one checkbox. Only those data user selected should be seen and a TOTAL row needs to be added at the bottom.
What I tried is on the bottom but it is not working well - TOTAL row is not there. My question is how I can add the Total row there, and is there any more professional way to provide this query. Thanks.
declare #interval03 bit -- 0 to 3
declare #interval06 bit -- 4 to 6
declare #interval09 bit -- 7 to 9
declare #interval12 bit -- 10 to 12
Select *, sum(timelong)
From myTable
Where (#interval03=1 and timelong<4)
or
(#interval06=1 and timelong>3 and timelong<7)
or
(#interval09=1 and timelong>6 and timelong<10)
or
(#interval12=1 and timelong>9 and timelong<13)
group by id, name
Try grouping sets:
Select ID, isnull(Name, 'TOTAL'), sum(timelong)
From myTable
Where (#interval03=1 and timelong <= 3)
or
(#interval06=1 and timelong between 4 and 6)
or
(#interval09=1 and timelong between 7 and 9)
or
(#interval12=1 and timelong >= 10)
group by grouping sets ((ID, name), ())
Assuming from your query that timelong is an int, I've simplified your where a little as well.
More information on grouping sets, rollup, and cube: https://technet.microsoft.com/en-us/library/bb522495(v=sql.105).aspx
TRY This..One more way to add totals...
declare #table Table (id INT,name VARCHAR(10), timelong INT)
insert into #table (id ,name, timelong) VALUES (1, 'Eray', 2)
insert into #table (id ,name, timelong) VALUES (1 ,'Jack' ,1)
insert into #table (id ,name, timelong) VALUES (1 ,'Ali' , 7)
insert into #table (id ,name, timelong) VALUES (1 ,'john' ,3)
insert into #table (id ,name, timelong) VALUES (1 ,'Roby' , 5)
insert into #table (id ,name, timelong) VALUES (1 ,'Mike' ,4)
insert into #table (id ,name, timelong) VALUES (1 ,'Josh' ,11)
declare #interval03 bit=1 -- 0 to 3
declare #interval06 bit -- 4 to 6
declare #interval09 bit -- 7 to 9
declare #interval12 bit -- 10 to 12
DECLARE #result TABLE (ID INT,Name VARCHAR (30),TimeLong INT)
INSERT INTO #result
Select id, name, sum(timelong) timelong
From #table
Where (#interval03=1 and timelong<4)
or (#interval06=1 and timelong>3 and timelong<7)
or (#interval09=1 and timelong>6 and timelong<10)
or (#interval12=1 and timelong>9 and timelong<13)
group by id, name
INSERT INTO #result
SELECT MAX(ID) +100 ID,'Total' Name,SUM(TimeLong) TimeLong
FROM #result
HAVING COUNT(*)<>0
SELECT * FROM #result

Add empty rows to results

I want to add empty rows to results fetched from a select statement. For example, if the select query fetch 4 rows then 2 empty rows needs to be fetched. Objective should be the number of rows fetched should be 6 every time. The number of rows fetched will be 6 maximum if there are 6 rows with data.
Any idea?
In SQL-SERVER You can create temp table to update It with empty rows and you can use WHILE to insert desired number of rows with empty values. Something like:
-- Create temp table to update data with empty rows
CREATE TABLE #HoldEmptyRows
(
Id NVARCHAR(20),
CustomerName NVARCHAR(20),
CustomerEmail NVARCHAR(20)
)
-- Insert data from SourceTable to temp
INSERT INTO #HoldEmptyRows
SELECT * FROM SourceTable
-- Do while count from temp table < of desired number insert empty rows
WHILE ((SELECT COUNT(*) cnt FROM #HoldEmptyRows) < 6)
BEGIN
INSERT INTO #HoldEmptyRows VALUES ('', '', '')
END
SELECT * FROM #HoldEmptyRows
DEMO AT SQL FIDDLE
Try the below logic:
with cte as
(
select 0 as col1
union all
select col1+1 from cte where cte.col1<10
)
select * into #temp1 from cte
create table #test
(rownum int,col1 varchar(100))
declare #i int=1
while (#i<=6)
begin
insert into #test
select * from
(select row_Number() over (order by (Select 0))rownum, * from #temp1)x
where rownum=#i
Set #i=#i+1
end
select case when rownum>4 then '' else col1 end as col1 from #test

T/SQL - Semi-manual Identity Column Insertion

Initial Query
DECLARE #Table1 TABLE (ID int, Value varchar(50))
DECLARE #Table2 TABLE (Value varchar(50))
DECLARE #MaxID1 int
DECLARE #MaxID2 int = 52
INSERT INTO #Table1 (ID, Value)
Values (1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five')
INSERT INTO #Table2 (Value)
Values ('Six'),('Seven'),('Eight'),('Nine'),('Ten')
SELECT * FROM #Table1
SELECT * FROM #Table2
SELECT #MaxID1 = MAX(ID) FROM #Table1
SELECT #MaxID1 Scenario1, #MaxID2 Scenario2
Expected Outcome of #Table1 after inserting values (Value field) from #Table2
// (Scenario #1 using #MaxID1)
ID Value
1 One
2 Two
3 Three
4 Four
5 Five
6 Six
7 Seven
8 Eight
9 Nine
10 Ten
// (Scenario #2 using #MaxID2)
ID Value
1 One
2 Two
3 Three
4 Four
5 Five
52 Six
53 Seven
54 Eight
55 Nine
56 Ten
How do I semi-manually insert ID values into an Identity column (ID) while executing INSERT query on that table (#Table1) from another table (#Table2)? In the first scenario, I wish to take the Max(ID) from #Table1 and add 1 to it and keep adding records. In the second scenario, I wish to take a predefined # and then start adding a record where first new record's ID would be the predefined values and all subsequent new records would be Max(ID) + 1.
Thank you
UPDATED #Table 1 does NOT have identity constraint.
If you want to insert an arbitrary int value into an identity column, use IDENTITY_INSERT:
SET IDENTITY_INSERT [table_name] ON;
Only one table at a time for a given session can have this property on. Make sure you turn it off when done:
SET IDENTITY_INSERT [table_name] OFF;

Any standard SQL expression to sort results base on IN expression [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
SQL - order by list order
Is there any standard SQL expression to sort results exactly base on IN expression. For example to return the results of the following query so that 2, 4, 6, 8 are returned serially?
SELECT * FROM SOMETABLE WHERE ID IN (2, 4, 6, 8)
The closest thing I can think of is doing a JOIN instead of an IN to a table with the original order with their ordinal rank
SELECT * FROM SOMETABLE INNER JOIN SOMETABLE2 ... etc
ORDER BY SOMETABLE2.original
If you have full controlled over your SQL rendering, then use a CASE expression:
ORDER BY CASE ID
-- render WHEN clauses in the desired order
WHEN 2 THEN 1
WHEN 4 THEN 2
WHEN 6 THEN 3
WHEN 8 THEN 4
END
Assuming you can pass the ids as a fixed delimited string, you can do the following :
-- Populate a number table
DECLARE #Temp Table(Number int)
INSERT INTO #Temp VALUES(1)
INSERT INTO #Temp VALUES(2)
INSERT INTO #Temp VALUES(3)
INSERT INTO #Temp VALUES(4)
INSERT INTO #Temp VALUES(5)
INSERT INTO #Temp VALUES(6)
INSERT INTO #Temp VALUES(7)
INSERT INTO #Temp VALUES(8)
INSERT INTO #Temp VALUES(9)
INSERT INTO #Temp VALUES(10)
SELECT TOP 8000 Number = IDENTITY(int,1,1) INTO [dbo].Numberos FROM #TEMP t1, #TEMP t2, #TEMP t3, #TEMP t4
ALTER TABLE [dbo].[Numbers] ADD CONSTRAINT [PK_Numbers] PRIMARY KEY CLUSTERED ([Number])
-- This function splits a fixed delimited string into a table object
CREATE FUNCTION [dbo].[fixstring_single](#str text, #itemlen tinyint)
RETURNS TABLE
AS
RETURN (SELECT listpos = n.Number,
str = substring(#str, (#itemlen + 1) * (n.Number - 1) + 1, #itemlen)
FROM Numbers n
WHERE n.Number <= (datalength(#str)+1) / (#itemlen+1))
DECLARE #ids varchar(100);
SET #ids = '00002 00001 00004';
-- Join to the number table ordered by the posisiton in the ids string
SELECT * FROM TestT INNER JOIN fixstring_single(#ids, 5) S ON TestT.ID = S.Str ORDER BY S.listpos