How to conditionally exclude or add columns when calculating row total - tsql

I have a stored procedure with a parameter defined like below
#CategoryNames NVARCHAR(MAX)
The above parameter gets a comma separated string from the application, for example the value can be like this #StaffCategoryIds=N'Category1,Category2,Category3,Category4,Category5'
Then i have the sample below sql query
SET #sql = #sql + 'TypeId,
TypeName,
Condition,
Region,
(Category1 + Category2 + Category3 + Category4 + Category5) AS Total INTO ##QueryResults
FROM Table1;'
When computing my Total column in the query above, how can i first check whether a category column (say Category2 or Category5) exists in my #StaffCategoryIds comma separated string before including it in the computation of my Total column?
Eg. if 'Category2' exists in #StaffCategoryIds, then i include it in computation of Total else i exclude it.

Try:
DECLARE #CategoryNames NVARCHAR(MAX) = N'Category1,Category2,Category3,Category4,Category5',
#sql NVARCHAR(MAX) = ''
SET #sql = 'SELECT TypeId,
TypeName,
Condition,
Region, ('+ REPLACE(#CategoryNames,',','+')+')
AS Total INTO ##QueryResults
FROM Table1;'
SELECT #SQL
It returns:
SELECT TypeId,
TypeName,
Condition,
Region, (Category1+Category2+Category3+Category4+Category5)
AS Total INTO ##QueryResults
FROM Table1;
Then you can Execute that statement:
EXEC #Sql

You can validate column names again system table "sys.columns" and whatever rows are returned , concatenate them as shown above to tun your query
SELECT [name]
FROM
sys.syscolumns
WHERE [name] IN ('Col1,Col2...ColN')
AND OBJECT_NAME(id) = 'TableName'

Related

Could not get desired column names using MDX in SQL Openquery. Need MEMBERs instead of complete hierarchy in columns name

Below is the TSQL I have written to fetch execute MDX using Openquery. However, I am unable to get columns in required format. Need columns title as Member only and Total column at the end of the table
DECLARE #DateFrom varchar(100)
SET #DateFrom = '2022-03-01'
DECLARE #DateTo varchar(100)
SET #DateTo = '2022-03-30'
DECLARE #Measure varchar(100)
SET #Measure = '[Measures].[Total Items]';
SET #sql = 'SELECT *
FROM OPENQUERY(POSCUBE,''
SELECT
(
[Date].[FirstDateOfWeek].Members,
{
'+#Measure+'
}
)
ON COLUMNS,
ORDER
(
(
[Product].[ProductName].Children,
[Product].[BrandName].Children
)
,
[Measures].[Total Items]
,
BDESC
)
ON ROWS
FROM [Model]
WHERE
([Date].[Date].['+#DateFrom+'] : [Date].[Date].['+#DateTo+']
) '')'
PRINT (#sql)
EXEC (#sql)
This is giving me below result
Current Result
I need result something like this where ALL (Row Total is at the end and Column Titles are Members value)
Required Result

SQL server Query to get result after calculation

Below is the code
create table #temp(nm varchar(10))
insert into #temp values ('1+2')
insert into #temp values ('(1+2)*3')
select * from #temp
I need the result as the mathematical calculation answers
The result should be 3 in the first row and 9 in the second row. can you guide me with a query for the same
SQL Sever does not support macro substitution, nor does it have an EVAL() function. This leaves Dynamic SQL
Example
Declare #YourTable Table (id int,nm varchar(150))
Insert Into #YourTable Values
(1,'1+2')
,(2,'(1+2)*3')
,(3,'datediff(DAY,''2018-01-01'',getdate())') -- Added Just for Fun
Declare #SQL varchar(max) = Stuff((Select ',' + concat('(',ID,',',nm,')')
From #YourTable A
For XML Path (''))
,1,1,'')
Exec('Select * from (values ' + #SQL + ')A([ID],[Value])')
Returns
ID Value
1 3
2 9
3 1099

Is there a way to dynamically create tables without knowing how many columns the table will have beforehand?

The following query uses a pivot to turn the values in field [expireDate Year-Month] into column headings. Because the number of year-months regularly increases and is not fixed, this is done dynamically.Is there a way to also dynamically create a table from the output without knowing how many columns the table will have beforehand?
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
--Get unique values of pivot column
SELECT #PivotColumns= COALESCE(#PivotColumns + ',','') + QUOTENAME([expireDate Year-Month])
FROM (SELECT DISTINCT [expireDate Year-Month] FROM REPORTING_DATA.tableau.vw_vehicleInspDetailsHistMonthlyFinal) AS PivotExample
SELECT #PivotColumns
--Create the dynamic query with all the values for
--pivot column at runtime
SET #SQLQuery =
N'SELECT DISTINCT Vehicle#, ' + #PivotColumns + '
FROM REPORTING_DATA.tableau.vw_vehicleInspDetailsHistMonthlyFinal
PIVOT( MAX(inspectionResult)
FOR [expireDate Year-Month] IN (' + #PivotColumns + '))
AS P
ORDER BY Vehicle# '
SELECT #SQLQuery
--Execute dynamic query
EXEC sp_executesql #SQLQuery

How Coalesce works in sql server?

Create table test(Names varchar(100) primary key )
insert into test values('Hugeman')
insert into test values('Jack')
insert into test values('William')
insert into test values('Kevin')
insert into test values('Peter')
Query 1:
declare #sql varchar(100)
select #sql = coalesce(#sql+'+','')+Names from test order by names-- where object_id =object_id('temp')
print #sql
This will result as
Hugeman+Jack+Kevin+Peter+William
Query 2
declare #sql varchar(100)
select #sql = coalesce(Names+'+','') from test order by names-- where object_id =object_id('temp')
print #sql
This will results William+
As per the documentation of coalesce, will return the first not null value. So it has to result Hugeman+. But it returns the entire rows.
Why query2 haven't done the same ?
This is not stricly connected to COALESCE.
Try these SELECTs:
DECLARE #sql1 AS VARCHAR(1000)
SELECT #sql1 = ISNULL(#sql1, '') + Names FROM test ORDER BY Names
PRINT #sql1
DECLARE #sql2 AS VARCHAR(1000)
SELECT #sql2 = Names FROM test ORDER BY Names
PRINT #sql2
So what happened? For EACH record selected:
in query 1 you keep adding values to #sql
in query 2 you reset #sql as the last name extracted
I don't understand exactly what you want to obtain from your SELECT, but a better example of COALESCE could be:
CREATE TABLE TEST2(Name VARCHAR(100) PRIMARY KEY, Telephone VARCHAR(10), Mobile VARCHAR(10))
INSERT INTO TEST2 VALUES('Hugeman', 1, 2)
INSERT INTO TEST2 VALUES('Jack', NULL, 3)
INSERT INTO TEST2 VALUES('William', 4, NULL)
INSERT INTO TEST2 VALUES('Kevin', 5, 6)
INSERT INTO TEST2 VALUES('Peter', NULL, NULL)
SELECT Name,
COALESCE(Telephone, Mobile) AS Tel
FROM TEST2
#sql is on the right hand side on the first to get appended
On the last #sql is all alone on the left side and has the value of the last row
Query-1: Appending the values of all rows to #sql
Query-2: Re-setting values to #sql
The below is the rows with order by names
Hugeman
Jack
Kevin
Peter
William
Query-1 Appends all values to #sql.
Query-2 Re-writing values to #sql, so the last row in the list is William so when you print the variable the last re-assigned value is printed.
The COALESCE() function returns the first non null value from the from the columns as parameters in COALESCE() function.
e.g.
SELECTCOALESCE(null,null,1,2) ///return --1
SELECT Id, COALESCE(FirstName, MiddleName, LastName) AS Name
FROM tblEmployee //return 1st non null value from FirstName/MiddleName/LastName

Conversion failed when converting the varchar value '1, 2, 3' to data type int

I can't seem to find a solution to this problem. Following is my query:
Declare #MY_STUDENT_ID Varchar(100)
Select #MY_STUDENT_ID = COALESCE(#MY_STUDENT_ID + ',', '') + Convert(varchar, STUDENT_ID) From Some_TABLE Where FISCAL_YEAR = '2014'
SELECT * FROM Table_Students WHERE STUDENT_ID IN (#MY_STUDENT_ID)
Basically first query runs and give me all student IDs as a string concatenated with , for e.g. 1,2,3
And then this value is passed into second query but second query is giving this error which I have posted in title. No idea what to do so any help will be appreciated.
Type of STUDENT_ID field is int.
There is absolutely no need to mess about with comma delimited lists here.
Just use the sub query directly
SELECT *
FROM Table_Students
WHERE STUDENT_ID IN (SELECT StudentId
From Some_TABLE Where FISCAL_YEAR = '2014')
Your approach does not work as it ends up generating something with semantics of
SELECT *
FROM Table_Students
WHERE STUDENT_ID IN ('1,2,3')
Which is not the same as
SELECT *
FROM Table_Students
WHERE STUDENT_ID IN (1,2,3)
As it just is a single string parameter with contents that happen to resemble an in list, rather than 3 int parameters.
You could do so using dynamic SQL, but in this scenario, Martin SMith's answer seems to be better. Should you, however, wish to use dynamic SQL, this would be the way to do so (untested pseudo-code):
Declare #MY_STUDENT_ID varchar(100);
DECLARE #sql nvasrchar(max);
Select #MY_STUDENT_ID = COALESCE(#MY_STUDENT_ID + ',', '') + Convert(varchar, STUDENT_ID) From Some_TABLE Where FISCAL_YEAR = '2014'
SELECT #sql = 'SELECT * FROM Table_Students WHERE STUDENT_ID IN (' + #MY_STUDENT_ID + ')';
EXEC sp_executesql #sql;