SQL Server: create multiplication table - sql-server

I need help regarding this problem. I need to create a function that will accept an integer and return a 10x10 multiplication table starting from the input value.
Sample can be seen below.
INPUT = 2
OUTPUT =
2 3 4 5 6 7 8 9 10 11
2 4 6 8 10 12 14 16 18 20 22
3 6 9 12 15 18 21 24 27 30 33
4 8 12 16 20 24 28 32 36 40 44
5 10 15 20 25 30 35 40 45 50 55
6 12 18 24 30 36 42 48 54 60 66
7 14 21 28 35 42 49 56 63 70 77
8 16 24 32 40 48 56 64 72 80 88
9 18 27 36 45 54 63 72 81 90 99
10 20 30 40 50 60 70 80 90 100 110
11 22 33 44 55 66 77 88 99 110 121

try this:
DECLARE #StartNumber int
,#EndNumber int
SELECT #StartNumber=2
,#EndNumber=#StartNumber+9
;WITH AllNumbers AS
(
SELECT #StartNumber AS Number
, #StartNumber*(#StartNumber+0) AS Number1
, #StartNumber*(#StartNumber+1) AS Number2
, #StartNumber*(#StartNumber+2) AS Number3
, #StartNumber*(#StartNumber+3) AS Number4
, #StartNumber*(#StartNumber+4) AS Number5
, #StartNumber*(#StartNumber+5) AS Number6
, #StartNumber*(#StartNumber+6) AS Number7
, #StartNumber*(#StartNumber+7) AS Number8
, #StartNumber*(#StartNumber+8) AS Number9
, #StartNumber*(#StartNumber+9) AS Number10
UNION ALL
SELECT Number+1
, (Number+1)*(#StartNumber+0) AS Number1
, (Number+1)*(#StartNumber+1) AS Number2
, (Number+1)*(#StartNumber+2) AS Number3
, (Number+1)*(#StartNumber+3) AS Number4
, (Number+1)*(#StartNumber+4) AS Number5
, (Number+1)*(#StartNumber+5) AS Number6
, (Number+1)*(#StartNumber+6) AS Number7
, (Number+1)*(#StartNumber+7) AS Number8
, (Number+1)*(#StartNumber+8) AS Number9
, (Number+1)*(#StartNumber+9) AS Number10
FROM AllNumbers
WHERE Number<#EndNumber
)
SELECT * FROM AllNumbers a
OUTPUT:
Number Number1 Number2 Number3 Number4 Number5 Number6 Number7 Number8 Number9 Number10
------- ------- ------- ------- ------- ------- ------- ------- ------- ------- --------
2 4 6 8 10 12 14 16 18 20 22
3 6 9 12 15 18 21 24 27 30 33
4 8 12 16 20 24 28 32 36 40 44
5 10 15 20 25 30 35 40 45 50 55
6 12 18 24 30 36 42 48 54 60 66
7 14 21 28 35 42 49 56 63 70 77
8 16 24 32 40 48 56 64 72 80 88
9 18 27 36 45 54 63 72 81 90 99
10 20 30 40 50 60 70 80 90 100 110
11 22 33 44 55 66 77 88 99 110 121
(10 row(s) affected)
make it dynamic SQL to get the proper column names:
DECLARE #SQL varchar(5000)
,#StartNumber int
SET #StartNumber=2
SET #SQL='
DECLARE #StartNumber int
,#EndNumber int
SELECT #StartNumber='+CONVERT(varchar(3),#StartNumber)+'
,#EndNumber=#StartNumber+9
;WITH AllNumbers AS
(
SELECT #StartNumber AS [ ]
, #StartNumber*(#StartNumber+0) AS ['+CONVERT(varchar(3),#StartNumber+0)+']
, #StartNumber*(#StartNumber+1) AS ['+CONVERT(varchar(3),#StartNumber+1)+']
, #StartNumber*(#StartNumber+2) AS ['+CONVERT(varchar(3),#StartNumber+2)+']
, #StartNumber*(#StartNumber+3) AS ['+CONVERT(varchar(3),#StartNumber+3)+']
, #StartNumber*(#StartNumber+4) AS ['+CONVERT(varchar(3),#StartNumber+4)+']
, #StartNumber*(#StartNumber+5) AS ['+CONVERT(varchar(3),#StartNumber+5)+']
, #StartNumber*(#StartNumber+6) AS ['+CONVERT(varchar(3),#StartNumber+6)+']
, #StartNumber*(#StartNumber+7) AS ['+CONVERT(varchar(3),#StartNumber+7)+']
, #StartNumber*(#StartNumber+8) AS ['+CONVERT(varchar(3),#StartNumber+8)+']
, #StartNumber*(#StartNumber+9) AS ['+CONVERT(varchar(3),#StartNumber+9)+']
UNION ALL
SELECT [ ]+1
, ([ ]+1)*(#StartNumber+0) AS ['+CONVERT(varchar(3),#StartNumber+0)+']
, ([ ]+1)*(#StartNumber+1) AS ['+CONVERT(varchar(3),#StartNumber+1)+']
, ([ ]+1)*(#StartNumber+2) AS ['+CONVERT(varchar(3),#StartNumber+2)+']
, ([ ]+1)*(#StartNumber+3) AS ['+CONVERT(varchar(3),#StartNumber+3)+']
, ([ ]+1)*(#StartNumber+4) AS ['+CONVERT(varchar(3),#StartNumber+4)+']
, ([ ]+1)*(#StartNumber+5) AS ['+CONVERT(varchar(3),#StartNumber+5)+']
, ([ ]+1)*(#StartNumber+6) AS ['+CONVERT(varchar(3),#StartNumber+6)+']
, ([ ]+1)*(#StartNumber+7) AS ['+CONVERT(varchar(3),#StartNumber+7)+']
, ([ ]+1)*(#StartNumber+8) AS ['+CONVERT(varchar(3),#StartNumber+8)+']
, ([ ]+1)*(#StartNumber+9) AS ['+CONVERT(varchar(3),#StartNumber+9)+']
FROM AllNumbers
WHERE [ ]<#EndNumber
)
SELECT * FROM AllNumbers a'
exec(#SQL)
OUTPUT:
2 3 4 5 6 7 8 9 10 11
------ ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
2 4 6 8 10 12 14 16 18 20 22
3 6 9 12 15 18 21 24 27 30 33
4 8 12 16 20 24 28 32 36 40 44
5 10 15 20 25 30 35 40 45 50 55
6 12 18 24 30 36 42 48 54 60 66
7 14 21 28 35 42 49 56 63 70 77
8 16 24 32 40 48 56 64 72 80 88
9 18 27 36 45 54 63 72 81 90 99
10 20 30 40 50 60 70 80 90 100 110
11 22 33 44 55 66 77 88 99 110 121
(10 row(s) affected)

Here's a cross join solution for you:
DECLARE #StartNum int;
SET #StartNum = 1;
WITH numbers AS (
SELECT
N = #StartNum + number
FROM master..spt_values
WHERE type = 'P'
AND number BETWEEN 0 AND 9
),
products AS (
SELECT
n1.N,
PivotN = n2.N,
P = n1.N * n2.N
FROM numbers n1
CROSS JOIN numbers n2
)
SELECT
N,
P0 = MAX(CASE PivotN WHEN #StartNum + 0 THEN P END),
P1 = MAX(CASE PivotN WHEN #StartNum + 1 THEN P END),
P2 = MAX(CASE PivotN WHEN #StartNum + 2 THEN P END),
P3 = MAX(CASE PivotN WHEN #StartNum + 3 THEN P END),
P4 = MAX(CASE PivotN WHEN #StartNum + 4 THEN P END),
P5 = MAX(CASE PivotN WHEN #StartNum + 5 THEN P END),
P6 = MAX(CASE PivotN WHEN #StartNum + 6 THEN P END),
P7 = MAX(CASE PivotN WHEN #StartNum + 7 THEN P END),
P8 = MAX(CASE PivotN WHEN #StartNum + 8 THEN P END),
P9 = MAX(CASE PivotN WHEN #StartNum + 9 THEN P END)
FROM products
GROUP BY N
ORDER BY N
Like with KM's solution, it is possible to rewrite the above query to have dynamic column names, but then you wouldn't be able to use the resulting query in a TVF. A stored procedure would do. Here's a dynamic version of the same script:
DECLARE #StartNum int, #NumColumns varchar(max), #sql varchar(max);
SET #StartNum = 2;
SELECT
#NumColumns = COALESCE(#NumColumns + ', ', '')
+ '[' + CAST(#StartNum + number AS varchar) + ']'
FROM master..spt_values
WHERE type = 'P'
AND number BETWEEN 0 AND 9;
SET #sql =
'WITH numbers AS (
SELECT ' + CAST(#StartNum AS varchar) + ' + number AS N
FROM master..spt_values
WHERE type = ''P''
AND number BETWEEN 0 AND 9
),
products AS (
SELECT
n1.N,
PivotN = n2.N,
P = n1.N * n2.N
FROM numbers n1
CROSS JOIN numbers n2
)
SELECT
N, ' + #NumColumns + '
FROM products
PIVOT (MAX(P) FOR PivotN IN (' + #NumColumns + ')) p';
EXEC(#sql);

Try This:-
DECLARE #InitialValue int =2, #Height int =10, #Width int =10, #ColumnNames varchar(max), #RowNames varchar(max), #sql varchar(max);
SELECT #RowNames = #RowNames + '[' + CAST(#InitialValue + number AS varchar) + ']'
FROM master..spt_values WHERE type = 'P' AND number BETWEEN 0 AND #Height-2
SELECT #ColumnNames = COALESCE(#ColumnNames + ', ', '') + '[' + CAST(#InitialValue + number AS varchar) + ']'
FROM master..spt_values WHERE type = 'P' AND number BETWEEN 0 AND #Width-2
SET #sql =
'WITH numbers AS ( SELECT ' + CAST(#InitialValue AS varchar) + ' + number AS X FROM master..spt_values WHERE type = ''P''
AND number BETWEEN 0 AND ' + CAST(#Height-2 AS varchar) +'
),
products AS (
SELECT n1.X, PivotN = n2.X, P = n1.X * n2.X FROM numbers n1 CROSS JOIN numbers n2
)
SELECT X, ' + #ColumnNames + '
FROM products
PIVOT (MAX(P) FOR PivotN IN (' + #ColumnNames + ')) p'
EXEC(#sql)
-----------------------------------------------------------------------

Related

Select previous and next row with condition in MSSQL

ID BegCha EnCha Val
10 20 30 250
10 30 40 140
10 50 60 189
20 10 20 250
20 20 30 157
20 30 40 199
20 40 50 70
Find all the rows where value is above 249
select * from table where Val >249
select One row previous and one row after if the values are 50 of 250
select * from table where id in (select * from table where Val >249) and Val > 149
What I am expecting to get is as under:
ID BegCha EnCha Val
10 20 30 250
10 30 40 140
10 50 60 189
20 10 20 250
20 20 30 157
With this table
create table prueba(
id int ,
BegCha int,
EndCha int,
Val int);
this data
id BegCha EndCha Val
10 20 30 250
10 30 40 140
10 50 60 189
20 10 20 250
20 20 30 157
20 30 40 199
20 40 50 70
and this Query
WITH pruebaNumerada AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY id ASC) AS RowNumber,
id, BegCha, EndCha, val
FROM prueba
)
SELECT b.id, b.BegCha, b.EndCha, b.val
FROM pruebaNumerada a
inner join pruebaNumerada b on b.RowNumber between a.RowNumber-1 and a.RowNumber+1
WHERE a.val >=250;
I obtain this result
id BegCha EndCha val
10 20 30 250
10 30 40 140
10 50 60 189
20 10 20 250
20 20 30 157
Are looking for something like this?
SELECT *
FROM table
WHERE id IN
(
SELECT DISTINCT id
FROM table
WHERE Val >249
)
AND Val > 149

How to Sort Amount Number Negative and Positive Number In SQL server

I have working SQL Server.I have More than 20000 Lines Using SQL server.I have column Filed Name Amount. in Amount Filed Inserted negative and Positive Number .Now I want Sort Amount Field Negative and Positive Number
Example Like :
Entity ExpenseTypeCode ExpenseType Amount
11 043 Hotel 5
12 044 travel 23
13 045 drink 55
14 046 Dinner 23
15 047 airline 556
16 048 Hotel -5
I how Like More than 30000 LINES .IN my table i have Expense type but negative and Positive value
I want Sort My table Like negative and Positive order same value
Entity ExpenseTypeCode ExpenseType Amount
11 043 Hotel 5
16 048 Hotel -5 --> Want sort like this
12 044 travel 23
13 045 drink 55
14 046 Dinner 23
15 047 airline 556
How can i sort my table liKE ?
Use ABS Function in sorting:
ABS() : It will convert your negative value to positive
SELECT
*
FROM TableName
Order BY ABS(Amount)
If you wants if negative and positive value same and order should consider positive first then:
SELECT
*
FROM TableName
Order BY ABS(Amount),Amount*-1
Example:
Initial
Output
select * from #t t
order by expensetype,
case when amount > 0 then 1 else 2 end
result
Entity ExpenseTypeCode ExpenseType Amount
----------- --------------- ----------- -----------
15 47 airline 556
14 46 Dinner 23
13 45 drink 55
11 43 Hotel 5
16 48 Hotel -5
12 44 travel 23
If you are looking for matching pairs then something like this might be what you want
declare #t table(Entity int, ExpenseTypeCode int, ExpenseType varchar(10), Amount int)
insert into #t values
( 11, 043, 'Hotel' , 6),
( 8, 043, 'Hotel' , 5),
( 9, 043, 'Hotel' , 5),
( 10, 043, 'Hotel' , 5),
( 12, 044, 'travel' , 23),
( 13, 045, 'drink' , 55),
( 14, 046, 'Dinner' , 23),
( 15, 047, 'airline' , 556),
( 16, 048, 'Hotel' , -5),
( 17, 048, 'Hotel' , -5),
( 18, 043, 'Hotel' , -6),
( 19, 043, 'Hotel' , -6)
select t.*,row_number() over(partition by t.ExpenseType, t.amount order by t.entity) rn,t.amount as absamount
from #t t
where t.amount > 0
union all
select t.*,row_number() over(partition by t.ExpenseTypeCode, t.amount order by t.entity) rn, abs(t.amount)
from #t t
where t.amount < 0
order by t.expensetype,absamount,rn,t.amount desc
result
Entity ExpenseTypeCode ExpenseType Amount rn absamount
----------- --------------- ----------- ----------- -------------------- -----------
15 47 airline 556 1 556
14 46 Dinner 23 1 23
13 45 drink 55 1 55
8 43 Hotel 5 1 5
16 48 Hotel -5 1 5
9 43 Hotel 5 2 5
17 48 Hotel -5 2 5
10 43 Hotel 5 3 5
11 43 Hotel 6 1 6
18 43 Hotel -6 1 6
19 43 Hotel -6 2 6
12 44 travel 23 1 23
or possibly a full join
select s.*,t.* from
(
select t.*,row_number() over(partition by t.ExpenseType, t.amount order by t.entity) rn
from #t t
where t.amount > 0
) s
full join
(
select t.*,row_number() over(partition by t.ExpenseTypeCode, t.amount order by t.entity) rn
from #t t
where t.amount < 0
) t on t.expensetype = s.expensetype and t.rn = s.rn and abs(t.amount) = s.amount
order by s.expensetype
Entity ExpenseTypeCode ExpenseType Amount rn Entity ExpenseTypeCode ExpenseType Amount rn
----------- --------------- ----------- ----------- -------------------- ----------- --------------- ----------- ----------- --------------------
NULL NULL NULL NULL NULL 19 43 Hotel -6 2
15 47 airline 556 1 NULL NULL NULL NULL NULL
14 46 Dinner 23 1 NULL NULL NULL NULL NULL
13 45 drink 55 1 NULL NULL NULL NULL NULL
11 43 Hotel 6 1 18 43 Hotel -6 1
10 43 Hotel 5 3 NULL NULL NULL NULL NULL
8 43 Hotel 5 1 16 48 Hotel -5 1
9 43 Hotel 5 2 17 48 Hotel -5 2
12 44 travel 23 1 NULL NULL NULL NULL NULL

Spliting one row of record into multiple between two date

Can anybody help me out to do this:
My table data is like
Datefiled Field1 Field2 Field2 Field4
01-01-2012 ABC 10 15 17
01-04-2013 PQR 7 80 65
01-05-2014 XYZ 15 25 77
The output would look something like this
Month/Year Field1 Field2 Field2 Field4
01/2012 ABC 10 15 17
02/2012 ABC 10 15 17
03/2012 ABC 10 15 17
04/2012 ABC 10 15 17
.....
03/2013 ABC 10 15 17
04/2013 PQR 7 80 65
05/2013 PQR 7 80 65
06/2013 PQR 7 80 65
07/2013 PQR 7 80 65
.......
04/2014 PQR 7 80 65
05/2014 XYZ 15 25 77
Just create a calendar table, either one row per day or one row per month, and you can use a tally table (=virtual, constructed for example with a CTE) too and do something like this:
select
*
from
calendar c
cross apply (
select top 1 *
from yourtable y
where y.Datefiled < c.calendardate
order by Datefiled desc
) y
;WITH datat as (
SELECT *
FROM (VALUES
('2012-01-01', 'ABC', 10, 15, 17),('2012-12-12', 'LKJ', 16, 12, 13),
('2013-01-15', 'CVB', 16, 11, 19),('2013-04-01', 'PQR', 7, 80, 65),
('2014-04-24', 'XYZ', 15, 25, 77),('2014-05-17', 'DEF', 12, 40, 50)
) as t(Datefiled, Field1, Field2, Field3, Field4)
), cte AS (
SELECT CAST(MIN(Datefiled) AS DATE) as date_,
CAST(MAX(Datefiled) AS DATE) AS maxd
FROM datat
UNION ALL
SELECT DATEADD(day,1,date_), maxd
FROM cte
WHERE date_ < maxd
)
SELECT CAST([Month] as nvarchar(2)) + '/' + CAST([Year] as nvarchar(4)) as [Month/Year],
Field1,
Field2,
Field3,
Field4
FROM (
SELECT DISTINCT
MONTH(date_) as [Month],
YEAR(date_) as [Year],
Field1,
Field2,
Field3,
Field4
FROM cte c
LEFT JOIN (
SELECT TOP 1 WITH TIES CAST(DATEADD(MONTH, DATEDIFF(MONTH, 0, d1.Datefiled ), 0) as date) as [DateStart],
CAST(DATEADD(MILLISECOND, -3, DATEADD(MONTH, DATEDIFF(MONTH, 0, d2.Datefiled), 0)) as date) as [DateEnd],
d1.Field1,
d1.Field2,
d1.Field3,
d1.Field4
FROM datat d1
LEFT JOIN datat d2
ON d1.Datefiled < d2.Datefiled
ORDER BY ROW_NUMBER() OVER (PARTITION BY d1.Datefiled ORDER BY d2.Datefiled)
) as d
ON c.date_ between d.[DateStart] and ISNULL(d.[DateEnd],c.date_)
WHERE Field1 IS NOT NULL
) as t
ORDER BY [Year], [Month]
OPTION (MAXRECURSION 0)
Output:
Month/Year Field1 Field2 Field3 Field4
---------- ------ ----------- ----------- -----------
1/2012 ABC 10 15 17
2/2012 ABC 10 15 17
3/2012 ABC 10 15 17
4/2012 ABC 10 15 17
5/2012 ABC 10 15 17
6/2012 ABC 10 15 17
7/2012 ABC 10 15 17
8/2012 ABC 10 15 17
9/2012 ABC 10 15 17
10/2012 ABC 10 15 17
11/2012 ABC 10 15 17
12/2012 LKJ 16 12 13
1/2013 CVB 16 11 19
2/2013 CVB 16 11 19
3/2013 CVB 16 11 19
4/2013 PQR 7 80 65
5/2013 PQR 7 80 65
6/2013 PQR 7 80 65
7/2013 PQR 7 80 65
8/2013 PQR 7 80 65
9/2013 PQR 7 80 65
10/2013 PQR 7 80 65
11/2013 PQR 7 80 65
12/2013 PQR 7 80 65
1/2014 PQR 7 80 65
2/2014 PQR 7 80 65
3/2014 PQR 7 80 65
4/2014 XYZ 15 25 77
5/2014 DEF 12 40 50
(29 row(s) affected)

Dynamically add a groupid and find the distinct count sql server 2008

Source Data:
TID Pid OpID
1 41 1
1 41 2
1 44 1
1 69 1
1 248 1
1 255 1
1 255 2
4 41 1
4 41 2
4 44 1
4 69 1
4 248 1
4 255 1
4 255 2
6 41 1
6 44 1
6 69 1
6 248 1
6 255 1
6 255 2
15 41 1
15 248 1
15 255 1
15 255 2
16 41 1
16 248 1
16 255 1
16 255 2
output:
Pid OpID Unique TId_count
41 1 2
41 2 2
44 1 2
69 1 2
248 1 2
255 1 2
255 2 2
41 1 1
44 1 1
69 1 1
248 1 1
255 1 1
255 2 1
41 1 2
248 1 2
255 1 2
255 2 2
Rules:
1) At first i need to find what are the available PID and OperationID for each TID
2) later consider PID and OPID as a set(group) and find the possible combination of TID and display distinct TID count
Example:
i) for the PID {41,41,44,69,248,255,255} and OperationId {1,2,1,1,1,1,2} is falling in two tester {1,4} so I need the output TID count is 2.
ii) for the PID {41,44,69,248,255,255} and OperationId {1,1,1,1,1,2} is falling in single tester {6} so i need the output TID count is 1.
iii) Finally, for the PID {41,248,255,255} and OperationId {1,1,1,2} is falling in two tester {15,16} so i need the output TID count is 2.
I cannot imagine any use for this ... but check out this anyway:
select pid, opid, count(*) from
(select tid, pid, opid,
(SELECT ',' + cast(x.pid as nvarchar(10))
FROM #temp x
WHERE x.tid = t.tid
FOR XML PATH ('')) as PidGroup,
(SELECT ',' + cast(x.OpId as nvarchar(10))
FROM #temp x
WHERE x.tid = t.tid
FOR XML PATH ('')) as OpIdGroup
from #temp t) innerselect
group by pid, opid, PidGroup, opidgroup
it produces the output you want ... just replace #temp with your tablename.

How do I get a total from a SQL query with a caculated field

I have a table that lists visits to a clinic. I'd like to get a "histogram" of sorts showing how frequently patients visit the clinic along with totals. Here's some sample code (tested under MS SQL Server 2005) to show what I'm talking about:
CREATE TABLE #test (
visit_id int IDENTITY(1,1),
patient_id int
);
DECLARE #num_patients int;
SELECT #num_patients = 1000 + ABS(CHECKSUM(NEWID())) % 250;
INSERT INTO #test (patient_id)
SELECT TOP 15 PERCENT ABS(CHECKSUM(NEWID())) % #num_patients
FROM sysobjects a, sysobjects b;
-- SELECT COUNT(*) AS total_visits FROM #test;
-- SELECT COUNT(DISTINCT patient_id) AS distinct_patients FROM #test;
SELECT CASE GROUPING(num_pat_visits) WHEN 1 THEN 'Total'
ELSE CAST(num_pat_visits AS varchar(5)) END AS num_pat_visits,
COUNT(*) AS num_patients, num_pat_visits * COUNT(*) AS tot_pat_visit
FROM
(SELECT patient_id, COUNT(*) AS num_pat_visits FROM #test GROUP BY patient_id) a
GROUP BY num_pat_visits WITH ROLLUP
ORDER BY CAST(num_pat_visits AS int) DESC;
This gets me almost to where I want:
num_pat_visits num_patients tot_pat_visit
-------------- ------------ -------------
60 1 60
54 2 108
52 2 104
51 4 204
50 3 150
49 3 147
48 7 336
47 7 329
46 15 690
45 15 675
44 29 1276
43 36 1548
42 45 1890
41 45 1845
40 59 2360
39 71 2769
38 51 1938
37 72 2664
36 77 2772
35 74 2590
34 72 2448
33 82 2706
32 90 2880
31 74 2294
30 69 2070
29 47 1363
28 30 840
27 27 729
26 26 676
25 21 525
24 13 312
23 4 92
22 5 110
21 4 84
20 2 40
18 2 36
Total 1186 NULL
However, I can't seem to get SQL Server to display the total number of visits where it says NULL on the total row.
Any ideas?
I think you can just do:
sum(num_pat_visits) as tot_pat_visit
SELECT CASE GROUPING(num_pat_visits) WHEN 1 THEN 'Total'
ELSE CAST(num_pat_visits AS varchar(5)) END AS num_pat_visits,
COUNT(*) AS num_patients,
--num_pat_visits * COUNT(*) AS tot_pat_visit
sum(num_pat_visits) as tot_pat_visit
FROM
(SELECT patient_id, COUNT(*) AS num_pat_visits FROM #test GROUP BY patient_id) a
GROUP BY num_pat_visits WITH ROLLUP
ORDER BY CAST(num_pat_visits AS int) DESC;

Resources