SQL Server - Conditional DELETE based on SUM from two tables - sql-server

I want to delete a specified student from the Studies table, for a specified term, if their score reaches a value of above x sPoints. I did attempt to do this and it works if I only specify which score they must be below.
If I start specifying student ID and term number in the query, it deletes all students from Studies where the student ID and term matches the one in the query without bothering to check the score.
My attempt: Student S2 has a total of 45 points in term 2 (5 in HasStudied and 40 in Studies) so he shouldn't be deleted with this query. Yet he still gets deleted when I run this query.
I'm on MS SQL server 2014.
DELETE FROM Studies
FROM Studies a1
INNER JOIN (SELECT a.stID AS ha
FROM Studies a
INNER JOIN HasStudied wq ON wq.stID = a.stID
WHERE a.stID = 'S2' AND a.termNbr = 2
GROUP BY a.stID
HAVING (SUM(wq.sPoints) + (SUM(a.sPoints))) > 50) a2 ON a1.stID = a2.ha
Studies table
CREATE TABLE Studies
(
cID VARCHAR (5) NOT NULL,
stID VARCHAR (5) NOT NULL,
sPoints int,
termNbr int
CONSTRAINT STUDIES_PK PRIMARY KEY (cID, stID),
CONSTRAINT STUDIES_CID_FK
FOREIGN KEY (cID) REFERENCES Course (cID),
CONSTRAINT STUDIES_STID_FK
FOREIGN KEY (stID) REFERENCES Student (stID)
)
HasStudied table
CREATE TABLE HasStudied
(
cID VARCHAR (5) NOT NULL,
stID VARCHAR (5) NOT NULL,
grade VARCHAR (5),
sPoints int,
termNbr int
CONSTRAINT HASSTUDIED_PK PRIMARY KEY (cID, stID)
CONSTRAINT HASSTUDIED_CID_FK
FOREIGN KEY (cID) REFERENCES Course (cID),
CONSTRAINT HASSTUDIED_STID_FK
FOREIGN KEY (stID) REFERENCES Student (stID)
)
Data in HasStudies and Studies.
INSERT INTO HasStudied (cID, stID, grade, sPoints, termNbr) VALUES
('K1', 'S2', 'D', (SELECT cPoints FROM COURSE WHERE cID = 'K1'), 1),
('K2', 'S2', 'A', (SELECT cPoints FROM COURSE WHERE cID = 'K2'), 1),
('K3', 'S2', 'C', (SELECT cPoints FROM COURSE WHERE cID = 'K3'), 1),
('K1', 'S3', 'C', (SELECT cPoints FROM COURSE WHERE cID = 'K1'), 1),
('K2', 'S3', 'E', (SELECT cPoints FROM COURSE WHERE cID = 'K2'), 1),
('K3', 'S3', 'B', (SELECT cPoints FROM COURSE WHERE cID = 'K3'), 1),
('K4', 'S3', 'E', (SELECT cPoints FROM COURSE WHERE cID = 'K4'), 2),
('K5', 'S3', 'D', (SELECT cPoints FROM COURSE WHERE cID = 'K5'), 2)
INSERT INTO Studies (cID, stID, sPoints, termNbr) VALUES
('K1', 'S1', (SELECT cPoints FROM COURSE WHERE cID = 'K1'), 1),
('K2', 'S1', (SELECT cPoints FROM COURSE WHERE cID = 'K2'), 1),
('K3', 'S1', (SELECT cPoints FROM COURSE WHERE cID = 'K3'), 1),
('K4', 'S2', (SELECT cPoints FROM COURSE WHERE cID = 'K4'), 2),
('K5', 'S2', (SELECT cPoints FROM COURSE WHERE cID = 'K5'), 2),
('K6', 'S3', (SELECT cPoints FROM COURSE WHERE cID = 'K6'), 3)
EDIT 2
I did yet another test with the student S2 that has 45 points in total. If I do HAVING (SUM(wq.sPoints) + (SUM(a.sPoints))) > x) and set x to a number below 50, it deletes the student. If I set it to 50 and above, it doesn't delete the student. So even a number of 49 will delete the student.

Your query looks OK and seems to work like a charm... maybe there is an error in your data?
DECLARE #Studies TABLE(
cID VARCHAR (5) NOT NULL,
stID VARCHAR (5) NOT NULL,
sPoints int,
termNbr int
)
DECLARE #HasStudied TABLE(
cID VARCHAR (5) NOT NULL,
stID VARCHAR (5) NOT NULL,
grade VARCHAR (5),
sPoints int,
termNbr int
)
INSERT INTO #Studies VALUES ('AAA', 'SSS1', 7, 11), ('AAA', 'SSS1', 13, 11), ('AAA', 'SSS1', 30, 11)
INSERT INTO #Studies VALUES ('BBB', 'SSS2', 7, 11), ('BBB', 'SSS2', 13, 11)
INSERT INTO #HasStudied VALUES ('AAA', 'SSS1', 'A', 20, 11), ('BBB', 'SSS2', 'F', 0, 11)
DELETE FROM #Studies
FROM #Studies a1
INNER JOIN (SELECT a.stID as ha
FROM #Studies a
INNER JOIN #HasStudied wq ON wq.stID = a.stID
WHERE a.stID = 'SSS1' AND a.termNbr = 11
GROUP BY a.stID
HAVING SUM(wq.sPoints) + SUM(a.sPoints) > 50
) a2
ON a1.stID = a2.ha
SELECT *
FROM #Studies
Result:
cID stID sPoints termNbr
BBB SSS2 7 11
BBB SSS2 13 11

UPDATE
Using Union, you can get the combined set to then test for the total:
WITH a AS(
SELECT sPoints
FROM Studies
WHERE termNbr = 2 AND stID = 'S2'
UNION
SELECT sPoints
FROM HasStudied
WHERE termNbr = 2 AND stID = 'S2'
)
DELETE FROM Studies
WHERE termNbr = 2 AND stID = 'S2' AND (SELECT SUM(sPoints) FROM a) > 59;
Original
You could try organizing your query more like this, which might make it easier to read and input the parameters you are looking for:
DELETE FROM Studies
WHERE termNbr = 2 AND stID = 'Bob' AND stID IN(
SELECT s.stID FROM Studies s
JOIN HasStudied hs ON s.stID = hs.stID AND s.termNbr = hs.termNbr
WHERE s.termNbr = 2
GROUP BY s.stID
HAVING (SUM(s.sPoints) + SUM(hs.sPoints)) > 50
);
http://sqlfiddle.com/#!17/6ffb8/18

Related

Add incrementally row values of a column of type string

I have a table with the following values
UserID ParentID Levels Path
1 NULL 0 A1
5 1 1 A2
9 5 2 A3
43 9 3 A4
The output should be like followed :
UserID ParentID Levels FinalPath
1 NULL 0 A1/
5 1 1 A1/A2/
9 5 2 A1/A2/A3/
43 9 3 A1/A2/A3/A4/
Thanks in advance for any guidance on this.
Solution using a recusive common table expression.
Sample data
create table users
(
userid int,
parentid int,
levels int,
path nvarchar(100)
);
insert into users (userid, parentid, levels, path) values
(1, NULL, 0, 'A1'),
(5, 1, 1, 'A2'),
(9, 5, 2, 'A3'),
(43, 9, 3, 'A4');
Solution
with cte as
(
select u.userid, u.parentid, u.levels, u.path
from users u
where u.parentid is null
union all
select u.userid, u.parentid, u.levels, convert(nvarchar(100), c.path + '/' + u.path)
from users u
join cte c
on c.userid = u.parentid
)
select c.userid, c.parentid, c.levels, c.path + '/' as FinalPath
from cte c;
Fiddle
Here's a version that both calculates the Level and appends the Path.
Data
drop table if exists dbo.test_table;
go
create table dbo.test_table(
UserID int,
ParentID int,
[Path] varchar(5));
insert dbo.test_table([UserID], [ParentID], [Path]) values
(1,null, 'A1'),
(5,1, 'A2'),
(9,5, 'A3'),
(43,9, 'A4');
Query
;with recur_cte([UserId], [ParentID], h_level, [Path]) as (
select [UserId], [ParentID], 0, cast([Path] as varchar(100))
from dbo.test_table
where [ParentID] is null
union all
select tt.[UserId], tt.[ParentID], rc.h_level+1, cast(concat(tt.[Path], '/', rc.[Path]) as varchar(100))
from dbo.test_table tt join recur_cte rc on tt.[ParentID]=rc.[UserId])
select * from recur_cte;
Results
UserId ParentID h_level Path
1 NULL 0 A1
5 1 1 A1/A2
9 5 2 A1/A2/A3
43 9 3 A1/A2/A3/A4

4 table join with count query

I'm using a SQL Server database with 4 tables like this:
Product table: Product_id is the primary key of the table:
| Product_id | Product_name | Description |
Project table: Project_id is the primary key of the table, Product_id is the foreign key to the Product table.
| Project_id | Project_name | Project_start_date | Product_id |
Participant table: Participant_id is the primary key of the table, Project_id is the foreign key to the Project table.
| Participant_id | Participant_name | Participant_email | Project_ID |
Response table: Response_id is the primary key of the table, participant_id is a foreign key to the Participant table.
My question is is it possible I can join all 4 tables together and list product name, project name, participant email and get the count of participants for each project and all response for each project?
Edit:
I feel it's better I put my code here. This is what I've tried, so please do not tell me use JOIN only...
This is the code I got total participant:
SELECT
projects.Project_ID,
count(*) total_Participants,
projects.Project_Name,
projects.Product_ID,
products.Product_Name
FROM
Project projects
INNER JOIN Participant participant on
projects.Project_ID = participant.Project_ID
INNER JOIN Products products ON
products.Product_ID = projects.Product_ID
group by
projects.Project_ID,
projects.Project_Name,
projects.Product_ID,
products.Product_Name,
projects.Project_ID
ORDER BY
projects.Project_ID DESC
And this is the code I got total response:
SELECT
projects.Project_ID,
count(*) total_Participants,
projects.Project_Name,
projects.Product_ID,
products.Product_Name
FROM
Project projects
INNER JOIN Participant participant on
projects.Project_ID = participant.Project_ID
INNER JOIN Products products ON
products.Product_ID = projects.Product_ID
INNER JOIN Response Response ON
Response.Participant_ID = participant.Participant_ID
group by
projects.Project_ID,
projects.Project_Name,
projects.Product_ID,
products.Product_Name,
projects.Project_ID
ORDER BY
projects.Project_ID DESC
Is this a way I can use one query statement to get participant_email, total participants and total response all together?
Without an example of your expected result, this is the best I could come up with.
Some sample data:
declare #product table
(
product_id int,
product_name nvarchar(20)
);
insert into #product (product_id, product_name) values
(1, 'Product ABC'),
(2, 'Product DEF'),
(3, 'Product GHI');
declare #project table
(
project_id int,
project_name nvarchar(20),
product_id int
);
insert into #project (project_id, project_name, product_id) values
(1, 'Project 001', 1),
(2, 'Project 002', 1),
(3, 'Project 003', 2),
(4, 'Project 004', 3);
declare #participant table
(
participant_id int,
participant_name nvarchar(20),
participant_email nvarchar(20),
project_id int
);
insert into #participant (participant_id, participant_name, participant_email, project_id) values
(1, 'Andy', 'andy#host.org', 1),
(2, 'Beatrice', 'beatrice#host.org', 1),
(3, 'Charles', 'charles#host.org', 2),
(4, 'Charles', 'charles#host.org', 4),
(5, 'David', 'david#host.org', 3),
(6, 'Eve', 'eve#host.org', 2);
declare #response table
(
response_id int,
response_content nvarchar(100),
participant_id int
);
insert into #response (response_id, response_content, participant_id) values
(1, 'please', 1),
(2, 'provide', 2),
(3, 'sample', 2),
(4, 'data', 3),
(5, 'next', 5),
(6, 'time', 4),
(7, 'thank', 6),
(8, 'you', 6),
(9, '>.<', 6);
Possible solution, using Common Table Expressions (CTE's) to isolate the count subqueries:
with cte_part as
(
select proj.project_id, count(1) as 'participant_count'
from #project proj
join #participant part on part.project_id = proj.project_id
group by proj.project_id
),
cte_resp as
(
select proj.project_id, count(1) as 'response_count'
from #project proj
join #participant part on part.project_id = proj.project_id
join #response resp on resp.participant_id = part.participant_id
group by proj.project_id
)
select prod.product_name,
proj.project_name,
part.participant_email,
cp.participant_count,
cr.response_count
from #product prod
join #project proj on proj.product_id = prod.product_id
join #participant part on part.project_id = proj.project_id
join cte_part cp on cp.project_id = proj.project_id
join cte_resp cr on cr.project_id = proj.project_id
order by prod.product_name;
This gives me:
product_name project_name participant_email participant_count response_count
-------------------- -------------------- -------------------- ----------------- --------------
Product ABC Project 001 andy#host.org 2 3
Product ABC Project 001 beatrice#host.org 2 3
Product ABC Project 002 charles#host.org 2 4
Product ABC Project 002 eve#host.org 2 4
Product DEF Project 003 david#host.org 1 1
Product GHI Project 004 charles#host.org 1 1

How to get those hotelid which are not having any entry after the date of particular product name?

For an example:
I have a table t1 like:
ID Name Date Product
1 A 20170101 AT
2 B 20170101 BT
1 A 20160102 A
2 B 20170106 D
3 C 20190101 F
3 C 20190101 GT
3 C 20190102 D
Now I want to get those hotel list which is not having any entry after the date of (AT,BT,GT) product.
From Above table:
I need hotelname A result because if we see 3rd entry on table for name A it is on the 20160102 which is less than the date of (A-T) product, it means there is no entry after that.
I would suggest to first retrieve all records with - in the product since this seems to be your criteria here, right? Then you could left join the result to the original table and by this evaluate the mentioned rule concerning the date. Following an example:
CREATE TABLE t (
[ID] INT NULL,
[Name] VARCHAR (80) NULL,
[Date] INT NULL,
[Product] VARCHAR (80) NULL
);
INSERT INTO t VALUES
(1, 'A', 20170101, 'A-T')
,(2, 'B', 20170101, 'B-T')
,(1, 'A', 20160102, 'A')
,(2, 'B', 20170106, 'D')
,(3, 'C', 20190101, 'F')
,(3, 'C', 20190101, 'G-T')
,(3, 'C', 20190102, 'D');
WITH cte AS(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Date]) rn
,COUNT(*) OVER (PARTITION BY [Name]) cn
FROM t
)
SELECT [Name]
FROM cte
WHERE Product IN (N'AT', N'BT', N'GT')
AND rn = cn
see SQL fiddle for details: http://sqlfiddle.com/#!18/dde24/12/1

What would be the query for Employee who work for all the department?

What would be the query for the employee who worked for all the department. here department and employee have many to many cardinality.
The tables are:
CREATE TABLE employees
(
employee_id int NOT NULL CONSTRAINT pk_employees PRIMARY KEY,
employee_name nvarchar(128) NOT NULL CONSTRAINT uk_employees_employee_name UNIQUE
);
CREATE TABLE departments
(
department_id int NOT NULL PRIMARY KEY,
department_name nvarchar(128) NOT NULL CONSTRAINT uk_departments_department_name UNIQUE
);
CREATE TABLE department_employees
(
department_id int NOT NULL CONSTRAINT fk_department_employees_departments REFERENCES departments(department_id),
employee_id int NOT NULL CONSTRAINT fk_departement_employees_employees REFERENCES employees(employee_id),
CONSTRAINT pk_deparment_employees PRIMARY KEY (department_id, employee_id)
)
Sample data:
INSERT INTO employees
VALUES (1, 'John Doe'), (2, 'Jane Doe'), (3, 'William Doe'), (4, 'Margaret Doe')
INSERT INTO departments
VALUES (1, 'Accounting'), (2, 'Humman Resources'), (3, 'Marketing')
INSERT INTO department_employees
VALUES
(1, 1), (2, 1), (3, 1),
(2, 2), (2, 3),
(3, 3), (3, 4)
Expected results:
+-------------+---------------+
| employee_id | employee_name |
+-------------+---------------+
| 1 | John Doe |
+-------------+---------------+
This operation is called Relation Division: on Relational algebra.
It can be implemented in sql with a query like the following
SELECT *
FROM dbo.employees e
WHERE
NOT EXISTS (
SELECT *
FROM departments d
WHERE d.department_id NOT IN (
SELECT dp.department_id
FROM department_employees dp
WHERE dp.department_id = d.department_id AND dp.employee_id = e.employee_id
)
)
Notice that the query: "Give me the employees that work for all departments" is equivalent to "Give me all employees that there is no department that the employee is not working for"
You can try this below query.
Here in a variable all distinct count department has been taken from department master table. After that only those employee has been selected where count match with distinct linked department count in relation table.
declare #distinctDeptCount int
SET #DistinctDeptCount = (SELECT Count(Distinct department_id) FROM departments)
--SELECT #DistinctDeptCount
SELECT Distinct employees.employee_id, employee_name
from employees
where employees.employee_id in (
select employee_id from department_employees GROUP BY employee_id HAVING COUNT(department_id) = #distinctDeptCount
)
OR
SELECT Distinct employees.employee_id, employee_name
from employees
where employees.employee_id in (
select employee_id from department_employees GROUP BY employee_id HAVING COUNT(department_id) =
(SELECT Count(Distinct department_id) FROM departments)
)
The output is as shown below
employee_id employee_name
1 John Doe
Here is the live demo Emp. with all departments
You can try this
SELECT
emp.name
FROM
Employee emp
JOIN
EmpDept empd
ON
emp.EmployeeID = empd.EmpId
GROUP BY
emp.EmployeeID
HAVING
count(emp.EmployeeID) = (select count(1) from Department)

Tree data to flat data in SQL Server

I am facing the problem tree view to flat view, I have some data that has come from a tree, those are stored in a table that is presenting in my picture below left. I am saying the top level of tree is level1, and second level is level2 and so on. My expected result that is representing in my picture below right.
How can I convert my data to my expected result dynamically in SQL Server? We have to create dynamic column level1, level2, level3 and so on. Do you have any idea? Thanks.
Here is the sample data
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
Id INT NOT NULL,
SomeName VARCHAR(3) NOT NULL,
ParentId INT NULL
);
INSERT #TestData (Id, SomeName, ParentId) VALUES
(1, 'O', NULL),
(2, 'D1', 1),
(3, 'D2', 1),
(4, 'S1', 2),
(5, 'S2', 2),
(6, 'S1', 3),
(7, 'SP1', 3);
SELECT * FROM #TestData td;
You can query as below:
;With Cte as ( --Recursive CTE for traversing tree
Select *, convert(varchar(max),[name]) as NameLevel, 1 as Levl from #TreeData where ParentId is Null
Union all
Select t.Id, t.[Name], t.[ParentId], concat(c.NameLevel,',',t.[name]) as NameLevel, c.Levl + 1 as Levl from Cte c
inner join #TreeData t on c.Id = t.ParentId
)
Select * from (
select c.Id, c.Levl, a.[value]
,RowN = row_number() over(partition by Id order by Levl) from cte c
cross apply string_split(c.NameLevel,',') a
) sq
pivot(max([value]) for RowN in([1],[2],[3])) p --Pivot for getting all data
Output as below:
+---+------+------+----+
| 1 | 2 | 3 | Id |
+---+------+------+----+
| O | NULL | NULL | 1 |
| O | D1 | NULL | 2 |
| O | D2 | NULL | 3 |
| O | D1 | S1 | 4 |
| O | D1 | S2 | 5 |
| O | D2 | S1 | 6 |
| O | D2 | SP1 | 7 |
+---+------+------+----+
Below the input table and data I used:
Create Table #TreeData(Id int, [name] varchar(10), ParentId int)
Insert into #TreeData(id, [name], ParentId) values
(1,'O', null)
,(2,'D1', 1)
,(3,'D2', 1)
,(4,'S1', 2)
,(5,'S2', 2)
,(6,'S1', 3)
,(7,'SP1', 3)
IF OBJECT_ID('tempdb..#TreeData', 'U') IS NOT NULL
DROP TABLE #TreeData;
CREATE TABLE #TreeData (
Id INT NOT NULL,
SomeName VARCHAR(3) NOT NULL,
ParentId INT NULL
);
INSERT #TreeData (Id, SomeName, ParentId) VALUES
(1, 'O', NULL),
(2, 'D1', 1),
(3, 'D2', 1),
(4, 'S1', 2),
(5, 'S2', 2),
(6, 'S1', 3),
(7, 'SP1', 3);
--SELECT * FROM #TestData td;
;With Cte as ( --Recursive CTE for traversing tree
Select Id,SomeName,ParentId, convert(varchar(max),[SomeName]) as NameLevel, 1 as Levl from #TreeData where ParentId is Null
Union all
Select t.Id, t.[SomeName], t.[ParentId], (c.NameLevel +','+ t.[SomeName]) as NameLevel, c.Levl + convert(int, 1) as Levl
from Cte c
inner join #TreeData t on c.Id = t.ParentId
)
--select * from cte
Select * from (
select c.Id, c.Levl, a.Items
,RowN = row_number() over(partition by Id order by Levl) from cte c
cross apply split(c.NameLevel,',') a
) sq
pivot(max([Items]) for RowN in([1],[2],[3])) p --Pivot for getting all data
The following should give you the requested results.
Note: This solution relies on the use of an iTVF called tfn_Tally, I'll post the code for that below my answer.
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
Id INT NOT NULL,
SomeName VARCHAR(3) NOT NULL,
ParentId INT NULL
);
INSERT #TestData (Id, SomeName, ParentId) VALUES
(1, 'O', NULL),
(2, 'D1', 1),
(3, 'D2', 1),
(4, 'S1', 2),
(5, 'S2', 2),
(6, 'S1', 3),
(7, 'SP1', 3);
-- SELECT * FROM #TestData td;
--===========================================
--===========================================
IF OBJECT_ID('tempdb..#RecursionResults', 'U') IS NOT NULL
DROP TABLE #RecursionResults;
WITH
cte_Recursion AS (
SELECT
td.Id,
SomeName = CAST(CAST(td.SomeName AS BINARY(5)) AS VARBINARY(1000)),
--td.ParentId,
NodeLevel = 1
FROM
#TestData td
WHERE
td.ParentId IS NULL
UNION ALL
SELECT
td.Id,
SomeName = CAST(CONCAT(r.SomeName, CAST(td.SomeName AS BINARY(5))) AS VARBINARY(1000)),
NodeLevel = r.NodeLevel + 1
FROM
cte_Recursion r
JOIN #TestData td
ON r.Id = td.ParentId
)
SELECT
Id = ISNULL(r.Id, 0), r.SomeName, r.NodeLevel
INTO #RecursionResults
FROM
cte_Recursion r;
-- adding a clustered index Id eliminates the sort operation on final select.
ALTER TABLE #RecursionResults ADD PRIMARY KEY CLUSTERED (Id);
-----------------------------------------
DECLARE
#PivotCount INT = (SELECT MAX(rr.NodeLevel) FROM #RecursionResults rr),
#PivotCols VARCHAR(1000) = '',
#PivotCAV VARCHAR(8000) = '',
#sql VARCHAR(8000),
#Debug BIT = 0; -- set to 0 to execute, 1 to DeBug.
SELECT TOP (#PivotCount)
#PivotCols = CONCAT(#PivotCols, CHAR(13), CHAR(10), CHAR(9), 'L', t.n, '.Level_', t.n, ','),
#PivotCAV = CONCAT(#PivotCAV, CHAR(13), CHAR(10), CHAR(9), 'CROSS APPLY ( VALUES (CAST(SUBSTRING(rr.SomeName,', (t.n - 1) * 5 + 1, ', ', 5, ') AS VARCHAR(5))) ) L', t.n, ' (Level_', t.n, ')'
)
FROM
dbo.tfn_Tally(#PivotCount, 1) t;
SET #sql = CONCAT('
SELECT ',
STUFF(#PivotCols, 1, 1, ''), '
rr.Id
FROM
#RecursionResults rr',
#PivotCAV, '
ORDER BY
rr.Id;');
IF #Debug = 1
BEGIN
PRINT(#sql);
END;
ELSE
BEGIN
EXEC (#sql);
END;
Function code for tfn_Tally...
CREATE FUNCTION dbo.tfn_Tally
/* ============================================================================
07/20/2017 JL, Created. Capable of creating a sequense of rows
ranging from -10,000,000,000,000,000 to 10,000,000,000,000,000
============================================================================ */
(
#NumOfRows BIGINT,
#StartWith BIGINT
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)), -- 10 rows
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b), -- 100 rows
cte_n3 (n) AS (SELECT 1 FROM cte_n2 a CROSS JOIN cte_n2 b), -- 10,000 rows
cte_n4 (n) AS (SELECT 1 FROM cte_n3 a CROSS JOIN cte_n3 b), -- 100,000,000 rows
cte_Tally (n) AS (
SELECT TOP (#NumOfRows)
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) + #StartWith
FROM
cte_n4 a CROSS JOIN cte_n4 b -- 10,000,000,000,000,000 rows
)
SELECT
t.n
FROM
cte_Tally t;
GO
HTH,
Jason

Resources