How to SUM dynamic field names from temp table - sql-server

I have table a with bunch of 0's scattered across many columns which are dynamically named dates (e.g. 2017_09_28). I want to hide the rows where the sum of all of these dynamically named columns nets to 0.
Assuming I have to create a select statement...
SELECT * FROM (
Select *, (dynamic column 1 + dynamic column 2 + dynamic column 3) sum
FROM temp table) sbqy WHERE sum != 0
Not sure how to grab all of the dynamic column names! If there is an alternative solution, all ears, but cannot spell out each dynamic column, too many and will change week to week.

You can use dynamic sql to create a string and then run it with sp_executesql
declare #cmd varchar(4000) = ''
set #cmd = 'select * from temptable where ' + case when someLogicHere then 'dynamicColomn1' end + case when someLogicHere then '+ dynamicColomn2' end
+ case when someLogicHere then 'dynamicColomn3' end + ' !=0'
--print(#cmd)
exec sp_executesql #cmd

Related

MS SQL - CONTAINS full-text search w/ variable number of values, not using dynamic sql

I've created a full-text indexed column on a table.
I have a stored procedure to which I may pass the value of a variable "search this text". I want to search for "search", "this" and "text" within the full-text column. The number of words to search would be variable.
I could use something like
WHERE column LIKE '%search%' OR column LIST '%this%' OR column LIKE '%text%'
But that would require me to use dynamic SQL, which I'm trying to avoid.
How can I use my full-text search to find each of the words, presumably using CONTAINS, and without converting the whole stored procedure to dynamic SQL?
If you say you definitely have SQL Table Full Text Search Enabled, Then you can use query like below.
select * from table where contains(columnname,'"text1" or "text2" or "text3"' )
See link below for details
Full-Text Indexing Workbench
So I think I came up with a solution. I created the following scalar function:
CREATE FUNCTION [dbo].[fn_Util_CONTAINS_SearchString]
(
#searchString NVARCHAR(MAX),
#delimiter NVARCHAR(1) = ' ',
#ANDOR NVARCHAR(3) = 'AND'
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
IF #searchString IS NULL OR LTRIM(RTRIM(#searchString)) = '' RETURN NULL
-- trim leading/trailing spaces
SET #searchString = LTRIM(RTRIM(#searchString))
-- remove double spaces (prevents empty search terms)
WHILE CHARINDEX(' ', #searchString) > 0
BEGIN
SET #searchString = REPLACE(#searchString,' ',' ')
END
-- reformat
SET #searchString = REPLACE(#searchString,' ','" ' + #ANDOR + ' "') -- replace spaces with " AND " (quote) AND (quote)
SET #searchString = ' "' + #searchString + '" ' -- surround string with quotes
RETURN #searchString
END
I can get my results:
DECLARE #ftName NVARCHAR (1024) = dbo.fn_Util_CONTAINS_SearchString('value1 value2',default,default)
SELECT * FROM Table WHERE CONTAINS(name,#ftName)
I would appreciate any comments/suggestions.
For your consideration.
I understand your Senior wants to avoid dynamic SQL, but it is my firm belief that Dynamic SQL is NOT evil.
In the example below, you can see that with a few parameters (or even defaults), and a 3 lines of code, you can:
1) Dynamically search any source
2) Return desired or all elements
3) Rank the Hit rate
The SQL
Declare #SearchFor varchar(max) ='Daily,Production,default' -- any comma delim string
Declare #SearchFrom varchar(150) ='OD' -- table or even a join statment
Declare #SearchExpr varchar(150) ='[OD-Title]+[OD-Class]' -- Any field or even expression
Declare #ReturnCols varchar(150) ='[OD-Nr],[OD-Title]' -- Any field(s) even with alias
Set #SearchFor = 'Sign(CharIndex('''+Replace(Replace(Replace(#SearchFor,' , ',','),', ',''),',',''','+#SearchExpr+'))+Sign(CharIndex(''')+''','+#SearchExpr+'))'
Declare #SQL varchar(Max) = 'Select * from (Select Distinct'+#ReturnCols+',Hits='+#SearchFor+' From '+#SearchFrom + ') A Where Hits>0 Order by Hits Desc'
Exec(#SQL)
Returns
OD-Nr OD-Title Hits
3 Daily Production Summary 2
6 Default Settings 1
I should add that my search string is comma delimited, but you can change to space.
Another note CharIndex can be substanitally faster that LIKE. Take a peek at
http://cc.davelozinski.com/sql/like-vs-substring-vs-leftright-vs-charindex

Generate column name dynamically in sql server

Please look at the below query..
select name as [Employee Name] from table name.
I want to generate [Employee Name] dynamically based on other column value.
Here is the sample table
s_dt dt01 dt02 dt03
2015-10-26
I want dt01 value to display as column name 26 and dt02 column value will be 26+1=27
I'm not sure if I understood you correctly. If I'am going into the wrong direction, please add comments to your question to make it more precise.
If you really want to create columns per sql you could try a variation of this script:
DECLARE #name NVARCHAR(MAX) = 'somename'
DECLARE #sql NVARCHAR(MAX) = 'ALTER TABLE aps.tbl_Fabrikkalender ADD '+#name+' nvarchar(10) NULL'
EXEC sys.sp_executesql #sql;
To retrieve the column name from another query insert the following between the above declares and fill the placeholders as needed:
SELECT #name = <some colum> FROM <some table> WHERE <some condition>
You would need to dynamically build the SQL as a string then execute it. Something like this...
DECLARE #s_dt INT
DECLARE #query NVARCHAR(MAX)
SET #s_dt = (SELECT DATEPART(dd, s_dt) FROM TableName WHERE 1 = 1)
SET #query = 'SELECT s_dt'
+ ', NULL as dt' + RIGHT('0' + CAST(#s_dt as VARCHAR), 2)
+ ', NULL as dt' + RIGHT('0' + CAST((#s_dt + 1) as VARCHAR), 2)
+ ', NULL as dt' + RIGHT('0' + CAST((#s_dt + 2) as VARCHAR), 2)
+ ', NULL as dt' + RIGHT('0' + CAST((#s_dt + 3) as VARCHAR), 2)
+ ' FROM TableName WHERE 1 = 1)
EXECUTE(#query)
You will need to replace WHERE 1 = 1 in two places above to select your data, also change TableName to the name of your table and it currently puts NULL as the dynamic column data, you probably want something else there.
To explain what it is doing:
SET #s_dt is selecting the date value from your table and returning only the day part as an INT.
SET #query is dynamically building your SELECT statement based on the day part (#s_dt).
Each line is taking #s_dt, adding 0, 1, 2, 3 etc, casting as VARCHAR, adding '0' to the left (so that it is at least 2 chars in length) then taking the right two chars (the '0' and RIGHT operation just ensure anything under 10 have a leading '0').
It is possible to do this using dynamic SQL, however I would also consider looking at the pivot operators to see if they can achieve what you are after a lot more efficiently.
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

SQL to split Comma Separated values and compare it with a multi list value in SSRS

I have a field in my table which has multiple reason codes concatenated in 1 column.
e.g. 2 records
Reason_Codes
Record1: 001,002,004,009,010
Record2: 001,003,005,006
In my SSRS report the user will be searching for data using one of the above reason codes. e.g.
001 will retrieve both records.
005 will retrieve the second record
and so on.
Kindly advise how this can be achieved using SQL or Stored Procedure.
Many thanks.
If you are just passing in a single Reason Code to search on, you don't even need to bother with splitting the comma-separated list: you can just use a LIKE clause as follows:
SELECT tb.field1, tb.field2
FROM SchemaName.TableName tb
WHERE ',' + tb.Reason_Codes + ',' LIKE '%,' + #ReasonCode + ',%';
Try the following to see:
DECLARE #Bob TABLE (ID INT IDENTITY(1, 1) NOT NULL, ReasonCodes VARCHAR(50));
INSERT INTO #Bob (ReasonCodes) VALUES ('001,002,004,009,010');
INSERT INTO #Bob (ReasonCodes) VALUES ('001,003,005,006');
DECLARE #ReasonCode VARCHAR(5);
SET #ReasonCode = '001';
SELECT tb.ID, tb.ReasonCodes
FROM #Bob tb
WHERE ',' + tb.ReasonCodes + ',' LIKE '%,' + #ReasonCode + ',%';
-- returns both rows
SET #ReasonCode = '005';
SELECT tb.ID, tb.ReasonCodes
FROM #Bob tb
WHERE ',' + tb.ReasonCodes + ',' LIKE '%,' + #ReasonCode + ',%';
-- returns only row #2
I have blogged about something like this a long time ago. May be this will help: http://dotnetinternal.blogspot.com/2013/10/comma-separated-to-temp-table.html
The core solution would be to convert the comma separated values into a temporary table and then do a simple query on the temporary table to get your desired result.

How to pivot dynamic number of columns row result into a verticle result list

There is a single row of data in a table that will have a varying number of columns named C1, C2, C3.. etc. I can locate that row but i want to un-pivot those dynamic number of columns values into a single column result... I have researched a ton on pivot/unpivot stuff but all examples i've found don't seem to handle the dynamic number of columns in the results.
Native Results:
Col 1 Col 2 Col 3 Col 4 Col 5.... Col X
Id Name DOB City State
Desired Results:
ColumnNameTBD:
Id
Name
DOB
City
State
Thank You!
Tim
After feedback from to the question i was able to piece together the solution. I now have a way to physically instanciate structure from dynamic/inconsistent structure automatically.
DECLARE #sColumnNames As Varchar(5000)
DECLARE #sSQL AS Varchar(5000);
--Flatten List of Column Names
Select #sColumnNames = ' ' + (
Select '(' + COLUMN_NAME + '),' As 'data()'
From SMAR_STG.INFORMATION_SCHEMA.COLUMNS With (NoLock)
where TABLE_NAME = 'V_ETL_CTX_COREM_EXCEL_DTL_COLUMNS'
For XML PATH('')
) + ' '
--Get Rid or trailing Comma
Set #sColumnNames = substring(#Output,1,len(#Output) -1)
-- Assemble SQL Statement
Set #sSQL = 'SELECT Upivot AS X
FROM SMAR_STG.DBO.V_ETL_CTX_COREM_EXCEL_DTL_COLUMNS
CROSS apply (VALUES '
Set #sSql = #sSQL + #sColumnNames
Set #sSQL = #sSQL + ') cs (upivot) '
-- Execute
EXEC (#sSql)
This item was already resolved here
As you will see from the article from the link, you will need to use COALESCE function to achive this

Dynamic Stored Procedure Results to Table

I have a stored procedure that dynamically produces pivot results, passing sql for row defs, column to pivot, aggregate(field) to sum, and table name of aggregate. This works great, but i need to produce a table from these results to use in further calculations.
How can I dynamically save the results to a table within the stored procedure (temp or non temp) without knowing the output columns??
SELECT *
INTO #TempTable
FROM (Pivot Expression)
This will create a #TempTable with the results of whatever you have in the FROM clause, regardless of number/type of columns.
you didn't ask, but this is how I'm getting a set of column names from a view:
DECLARE #columns VARCHAR(1000)
SELECT #columns = COALESCE(#columns + ',[' + cast(fld as varchar) + ']',
'[' + cast(fld as varchar)+ ']')
FROM view
GROUP BY fld

Resources