count in dynamic name SQL Server - sql-server

I create a stored procedure in SQL Server:
ALTER PROCEDURE [dbo].[testChildren]
#Parent INT
AS
BEGIN
SET NOCOUNT ON;
WITH EntityChildren AS
(
SELECT
nname, nodeid, level, ncode, nparent
FROM
GrpItm
WHERE
nodeid = #Parent
UNION ALL
SELECT
e.nname, e.nodeid, e.level, e.ncode, e.nparent
FROM
GrpItm e
INNER JOIN
EntityChildren e2 ON e.nparent = e2.nodeid
)
SELECT COUNT(Level) AS [level]
FROM EntityChildren
END
How can I make each count level in row and named the row by level value like this:
| level 1 | level 2 | level 3 |
+---------+---------+---------+
| 2 | 3 | 1 |

If you want something closer to...
level | count
-------+-------
1 | 2
2 | 3
3 | 1
Then it would just be something like...
SELECT
level,
COUNT(*) AS row_count
FROM
EntityChildren
GROUP BY
level
But that's simpler than what you're already accomplished, so I may be missing the point of your question and comment?

This is only regarding to #MatBailie answer. If you have a table like his, you can pivot your data and get it as you request.
Table Created with Levels and counts
You need a script to populate this table with the values you need
create table dbo.myt (levels int, counts int)
insert into dbo.myt
values
(1 , 2),
(2 , 3),
(3 , 1)
SQL Code
DECLARE #ALIASNAME nvarchar(50) = 'Levels'
DECLARE #Str NVARCHAR(MAX);
DECLARE #Str2 NVARCHAR(MAX);
SELECT #Str = STUFF(
(
SELECT DISTINCT
','+'[Levels'+cast(levels as nvarchar(50))+']'
FROM dbo.myt FOR XML PATH('')
), 1, 1, '');
PRINT #Str
SET #str2 = N'select * from (
select cast('''+#ALIASNAME+'''+ cast(Levels as nvarchar(50)) as nvarchar(50)) as Levels,counts,ROW_NUMBER() over(PARTITION by levels order by counts) as rn
from dbo.myt
)x
PIVOT
(Max(counts) FOR Levels in ('+#Str+')
) as p';
PRINT #Str2;
EXEC (#Str2);
Your Stored proc
ALTER PROCEDURE [dbo].[testChildren]
#Parent INT
AS
BEGIN
SET NOCOUNT ON;
WITH EntityChildren AS
(
SELECT
nname, nodeid, level, ncode, nparent
FROM
GrpItm
WHERE
nodeid = #Parent
UNION ALL
SELECT
e.nname, e.nodeid, e.level, e.ncode, e.nparent
FROM
GrpItm e
INNER JOIN
EntityChildren e2 ON e.nparent = e2.nodeid
)
INSERT INTO dbo.myt (Levels,Counts)
SELECT
level, COUNT(*) AS row_count
FROM
EntityChildren
GROUP BY level
/* INSERT PIVOT SCRIPT AND INSERT INTO A NEW TABLE */
END
Result

Related

result of one stored procedure to input for Query showing null

I wrote two stored procedures
ALTER PROCEDURE [dbo].[GetPhysicalChildNodesAsString]
-- Add the parameters for the stored procedure here
#Book varchar(50),
#Vertical varchar(50)
AS
BEGIN
DECLARE #results nvarchar(max)
;WITH cte AS
(
SELECT a.BookID, a.ParentBookID, a.BookName
FROM DimBook a
WHERE BookName = #Book
UNION ALL
SELECT a.BookID, a.ParentBookID, a.BookName
FROM DimBook a JOIN cte c ON a.ParentBookID = c.BookID
and HighPortfolioID = ( select PortfolioID from portfolioMaster where PortfolioName = #Vertical and PortfolioType='HighPortfolio')
)
select #results = coalesce(#results + ',', '')+'''' + convert(varchar(max),BookName)+''''
from cte Where Len(BookName) < 20
select #results as Book
END
Above stored Proc returns below string
'Physical','Anish Vohra','Sandeep Bajoria','Nirav Desai','Sushil Mohta','Sahil Pasad','G R Poddar','Direct','Sales Broker','Internal Transfer','Sprint','Murji Meghan','Intra Oils & Fats','GGN','GGN1','GGN2','Book1','Book2','Book 3','Book4','Book5','Comglobal','Sunvin','PVOC','Afro Asian'
DECLARE #BooksList varchar(max)
DECLARE #t table(BookNames varchar(max) )
INSERT #t(BookNames)
EXEC #BooksList = GetPhysicalChildNodesAsString 'Physical','Enterprise'
SELECT #BooksList = BookNames FROM #t
select #BooksList as 'books'
select * from DimBook where BookName IN(select #BooksList as 'books') ----> reults only header of table Only. But if pass result string directly like below it is working. can you help me for why above query is not working
select * from DimBook where BookName IN('Physical','Anish Vohra','Sandeep Bajoria','Nirav Desai','Sushil Mohta','Sahil Pasad','G R Poddar','Direct','Sales Broker','Internal Transfer','Sprint','Murji Meghan','Intra Oils & Fats','GGN','GGN1','GGN2','Book1','Book2','Book 3','Book4','Book5','Comglobal','Sunvin','PVOC','Afro Asian') ----> getting correctly.

Split string using delimiter that the SSRS passes - select multiple values from the parameter

I have this stored procedure where I am trying to select multiple values from the parameter Bkt. This works okay when I select one value from Bkt but Bkt has different values that I want to be able to select from in the SSRS.
For example in this screenshot you can see that there are CFI and DPR inside of Bkt. I want to be able to select both CFI and DPR in Bkt.
I need to keep the stored procedure so I am trying to split the delimited string that SSRS passes. I can't figure it out. I tried changing the delimiter by using an expression in the Parameters mapping section but I couldn't figure that out either. I am just so lost.
This is my Stored Procedure
#Press varchar(10),
#BKT varchar (10)
AS
BEGIN
SET NOCOUNT ON;
select * From (
Select FAC,SPEC_NEW.Tread_Code, Case When cosw.tread_code = spec_new.tread_code Then 'Scheduled' else 'Alternative' end AS Size, COUNT(Distinct loc.serial ) QTY ,
ROW_NUMBER() OVER (
PARTITION BY FAC, SPEC_NEW.Tread_Code
ORDER BY fac, Case When cosw.tread_code = spec_new.tread_code Then 'Scheduled' else 'Alternative' end DESC, SPEC_NEW.Tread_Code
) AS r_num
FROM [TireTrack].[dbo].[cos_work] cosw with (nolock)
Inner Join [SharedData].dbo.spec_master Spec with (nolock) On spec.spec=Cosw.SPEC
Inner Join [SharedData].dbo.spec_master SPEC_NEW with (nolock) On SPEC_NEW.ARTICLE=SPEC.article
Inner Join [DataWarehouse].[dbo].[Locator] LOC with (Nolock) ON LOC.SPEC=SPEC_NEW.SPEC
Where Cosw.FAC=#press and Loc.BKT = #bkt
GROUP BY FAC, cosw.Tread_Code, SPec_new.Tread_Code, Loc.Bkt
) as a
where r_num=1
order by FAC
END
I have another Stored Procedure where I am getting Press and Bkt
AS
BEGIN
SET NOCOUNT ON;
Select distinct FAC as Press, Loc.BKT as Bkt
FROM [TireTrack].[dbo].[cos_work], [DataWarehouse].[dbo].[Locator] LOC
END
I was using this link as a reference
Here is a conceptual example for you how to handle comma separated parameter to a stored procedure.
SQL
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, vehicleMake VARCHAR(20));
INSERT INTO #tbl (vehicleMake) VALUES
('Chevrolet'),
('Tesla'),
('Audi'),
('Nissan');
DECLARE #ParameterList VARCHAR(max) = '1,2';
-- Method #1
-- XML and XQuery
-- SQL Server 2008 onwards
DECLARE #separator CHAR(1) = ',';
;WITH rs AS
(
SELECT xmldata = TRY_CAST('<root><r>' +
REPLACE(#ParameterList, #separator, '</r><r>') + '</r></root>' AS XML)
)
SELECT tbl.*
FROM rs CROSS APPLY xmldata.nodes('/root/r/text()') AS t(c)
INNER JOIN #tbl AS tbl ON tbl.id = c.value('.','INT');
-- Method #2
-- STRING_SPLIT()
-- SQL Server 2016 onwards
SELECT tbl.*
FROM #tbl AS tbl INNER JOIN
STRING_SPLIT(#ParameterList, ',') AS ss
ON tbl.ID = ss.value;
Output
+----+-------------+
| ID | vehicleMake |
+----+-------------+
| 1 | Chevrolet |
| 2 | Tesla |
+----+-------------+

Dynamic where clause sql loop

Following is the stored procedure
ALTER PROCEDURE [dbo].[get_data_Dyna]
{
#param1 varchar(max) = null,
#param2 varchar(max) = null,
#start varchar(max) = null,
#end varchar(max) = null
}
AS
SELECT * from table where
(#param1 IS NULL OR column1 IN (SELECT data FROM dbo.delimited_list_to_table(#param1,',')))
AND (#param2 IS NULL OR column2 IN (SELECT data FROM dbo.delimited_list_to_table(#param2,',')))
AND ....?????
How this is working :
All the parameters can be comma seperated
#param1 value can be 'Germany' or 'Germany,USA' or null. This is working as expected.
Same goes for #param2
I'm trying to include rest of the parameters which is expected to work as follows :
#start='0' and #end='100' : In this case, where clause will look like this
...AND val BETWEEN #start AND #end
#start='48,60' and #end='51,99' : In this case, where clause will look like this
...AND ((val Between 48 and 51) or (val Between 60 and 99))
#start='48,60,75' and #end='51,99,203' : In this case, where clause will look like this
...AND ((val Between 48 and 51) or (val Between 60 and 99) or (val Between 75 and 203))
I'm unable to include above 2nd/3rd point correctly. I tried to write it dynamically which is working for single values [Point 1], but how to write point 2/3 ?
Any help is greatly appreciated.
Ok, i think the best approach here would be to use temp tables or table variable.
Lets go with temp tables.
create table #StartEnd (start int not null, end int not null, primary key (start,end))
then we insert from #start and #end into it using dbo.delimited_list_to_table. Now i am not sure about your implementation of it, so i will assume the values are numbered
insert into #StartEnd
select starts.data, ends.data
from dbo.delimited_list_to_table(#start,',') as starts
join dbo.delimited_list_to_table(#end,',') as ends
on starts.index = ends.index
Now we have to filter the values. Two approaches. Join or Exists condition
...
join #StartEnd on val between start and end
...
and exists (select 1 from #StartEnd where val between start and end)
Hope this helps
there you go. The comments / explainations are within the query
-- create a sample table
declare #tbl table
(
val int
)
-- put in some sample data
insert into #tbl
values (48), (60), (51), (99), (75), (203)
-- these are the input parameter
declare #start varchar(100),
#end varchar(100)
-- and these are the input value
select #start = '48,60,75',
#end = '51,99,203'
-- the actual query
; with
start_end as
(
-- here i am using [DelimitedSplit8K][1]
select s = s.Item, e = e.Item
from dbo.[DelimitedSplit8K](#start, ',') s
inner join dbo.[DelimitedSplit8K](#end, ',') e
on s.ItemNumber = e.ItemNumber
)
select t.val
from #tbl t
where exists
(
select *
from start_end x
where t.val between x.s and x.e
)
you can get it here DelimitedSplit8K
Sample input (from our understanding, we guess the your data):
select
* into ##delimit
from (
values
(1 ,'Ger','Ind', 100 )
,(2 ,'Ind',Null, 10 )
,(3 ,'Ger',Null, 24 )
,(4 ,'Ind','Ger', 54 )
,(5 ,'USA','Ind', 56 )
,(6 ,Null,'USA', 75 )-- NULL. But USA is three time came.
,(7 ,'USA','USA', 60 )-- same country with diff val.
,(8 ,'USA','USA', 80 )-- same country with diff val.
) demilit(Id,FromPr,ToPr,Val)
select * from ##delimit
Procedure (you just use this instead of your procedure):
CREATE PROCEDURE [dbo].[get_data_Dyna]
(#param1 varchar(max) = NULL,
#param2 varchar(max) = NULL,
#start varchar(max) = NULL,
#end varchar(max) = NULL)
AS
BEGIN
SELECT *
FROM ##delimit d
JOIN
( --| Here we check the val btw #start and #end
SELECT DISTINCT
s.FinalColumn StartVal, --|
e.FinalColumn EndVal --|
FROM
dbo.WithoutDelimit (#start, ',') s --| S means 'Start'
JOIN
(SELECT *
FROM dbo.WithoutDelimit (#end, ',')) e ON s.id = e.id --| E means 'End'
) se --| se mean StartEnd
ON d.val BETWEEN se.StartVal AND se.EndVal --| Here YOUR CONDITION is accomplished
WHERE
( -- | checks whether
frompr IN -- | column1 in #param1 or not
(SELECT FinalColumn FROM dbo.WithoutDelimit (#param1,',') -- | frompr means, 'column1'
) OR #param1 is NULL -- |
)
and ( -- | checks whether
ToPr in ( -- | column2 in #param2 or not
select FinalColumn from dbo.WithoutDelimit (#param2,',') -- | frompr means, 'column2'
) or #param2 is null -- |
)
end
Call stored procedure:
[get_data_Dyna] null,'usa','75','100,' -- 6 rows
[get_data_Dyna] 'Ind,Ger',null,'1,15','20,30' --2 and 3 rows are selected.
[get_data_Dyna] 'usa','usa','50,60','55,79'
-- 7 and 8 has same country. But due to Val, 8 has been rejected.
[get_data_Dyna] NULL,'usa','70,60','80,79'
-- 6 and 7 and 8 has been selected. Due to val condition.
Function (called from the stored procedure):
alter function WithoutDelimit -- We use one function for all conditions.
(#Parameter varchar (max),
#delimit varchar (1))
returns #FinalTable table (
Id int identity (1,1) -- Auto increment
, FinalColumn varchar (max) -- It returns the values as a column.
) as
begin
;with cte as -- recursive cte.
(
select convert (varchar (255), #Parameter + #delimit) con
, convert (varchar (255), #Parameter + #delimit) want
union all
select convert (varchar (255), stuff (con, 1, CHARINDEX (#demilit,con),'') )
, substring (con, 1, CHARINDEX (#delimit, con) - 1)
from cte
where con <> ''
) insert into #FinalTable (FinalColumn)
select want from cte
where con <> want
return
end
Revert us, if query need update.

Assigning select results into variable in stored procedure in mssql?

I have the following select:
SELECT School_Type,COUNT(ID) from Schools where City_ID = 1 group by School_Type
I get results:
10 | 3
20 | 4
30 | 14
I want to put results that are:
type 10 to variable #ElementarySchools
type 20 to variable #HighSchools
type 30 to variable #ProfessionalSchools
and get this result back from the Stored Procedure.
How do I do this ?
something like this? :)
declare #val varchar(max) = ''
select #val = #val + rtrim(foryear) + ' | ' + RTRIM( COUNT(*)) + ',' from mytable
group by ForYear
select #val
Using a table variable like this:
declare #tmp table (School_Type int, School_Count int)
insert into #tmp
SELECT School_Type,COUNT(ID) from Schools where City_ID = 1 group by School_Type
select #ElementarySchools=School_Count from #tmp where School_Type=10
select #HighSchools=School_Count from #tmp where School_Type=20
select #ProfessionalSchools=School_Count from #tmp where School_Type=30

TSQL calculating sum of numerous fields

I have this kind of data:
Date Count1 Count2 Count3 ... Countxx
01-05-2012 1 0 1 2
01-05-2012 2 1 3 0
01-05-2012 2 3 3 1
02-05-2012 1 3 2 0
02-05-2012 5 2 0 0
and I need to calculate sum of respective fields (Count1 to Countxx) grouped by date and wrote this SQL:
select sum(count1), sum(count2), sum(count3), .. , sum(countxx)
from table1 group by date
my first question: is there any way in SQL server to do this automatically (without knowing number of fields, since the name and number of the fields will be different each time, thus making writing the SQL manually very cumbersome).
secondly, how to calculate value from current row minus previous row, and average of previous 7 rows?
Thanks!
create procedure USP_FindSum #tablename varchar(100)
as
begin
create table #temp(id int identity(1,1),name varchar(100))
declare #sqlcmd nvarchar(max)=''
SET #sqlcmd= N'Insert into #temp select name from sys.columns col_table where
col_table.object_id=object_id('''+#tablename+''')'
EXEC sp_executesql #sqlcmd
declare #sqlseg varchar(max)=''
declare #tempcount int
declare #i int=1
select #tempcount=COUNT(id) from #temp
while(#i<=#tempcount)
BEGIN
declare #CName varchar(100)
SELECT #CName= name from #temp where id=#i
if(#i!=#tempcount)
SET #sqlseg=+#sqlseg+'sum('+#CName+')'+','
else
SET #sqlseg =+#sqlseg+'sum('+#CName+')'
SET #i=#i+1
END
SET #sqlcmd=N'select '+#sqlseg+' from '+#tablename
EXEC sp_executesql #sqlcmd
DROP TABLE #temp
END
Assuming all the columns in the table are summable. As your requirement is weird this workaround may also be so.
Just pass the table name as parameter and execute,
Exec USP_FindSum '<tablename here>'
There is no way to sum a variable list of columns, you have to specify them all.
One way to look up the previous row is outer apply, like:
select Date
, cur.count1 - isnull(prev.count1,0) as Delta1
from Table1 cur
outer apply
(
select top 1 *
from Table1 prev
where prev.Date < cur.Date
order by
prev.Date desc
) prev
Another way is to join the tables based on row_number():
; with t1 as
(
select row_number() over (order by Date) as rn
, *
from Table1
)
select Date,
, cur.count1 - isnull(prev.count1,0) as Delta
from t1 cur
left join
t1 prev
on cur.rn = prev.rn + 1

Resources