How to create a SQL view with variable where clause - sql

I have a table with 37 columns. The table is populated from daily csv files. I need to create a view that filters only the previous month data set. The posting date column is a string variable in the form 20131219. I have a function that uses date functions to determine the current month, then returns a string with the year and month prior. This query returns the data set I need, but I can't figure out how to create a view that allows the variables and function call. **the paramater '2013' doesn't do anything. I couldn't get the function to work without one, so added something.
declare #newstring varchar(6)
set #newstring = [dbo].[GetPrevYearMonth]('2013')
select * from dbo.SAE_EDATA_LV
where [GTR-POSTING-DATE] like #newstring+'%'
I know I could create a function with a table return type, but that's very tedious for the number of columns.
Any help would be greatly appreciated.

Change your View to an inline Table-Valued Function (iTVF). An iTVF is really just a parametized View anyway.
You use it the exactly the same, except that you have to also specify parameters.
Alternatively, you can create an iTVF wrapper for your View:
CREATE FUNCTION dbo.fnSAE_EDATA_LV(#newstring varchar(6))
RETURNS TABLE As
select *
from dbo.SAE_EDATA_LV
where [GTR-POSTING-DATE] like #newstring+'%'
You should also know that long column lists can just be dragged from a Table/View/Table-Valued function's icon/column folder on the SSMS explorer pane and dropped into a SQL session pane.

Related

Loop in BigQuery (SQL - GOOGLE CLOUD)

I would like to know how to perform a loop in bigquery to create a table changing only its name and the where clause.
Basically as an example:
I would like, for example, to create the table three times according to vector_a, that is, we would have a table with the name 01,02,03 and filtering from vector_b that would also change to create the table with std1 at the beginning and then std2 and std3. Being these variables inside the array in string format.
See https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#for-in
You can use something like
DECLARE vector_a ARRAY<STRING>;
SET vector_a = ['_01', '_02', '_03'];
FOR loop_variable_name IN (SELECT * FROM UNNEST(vector_a))
DO
-- use loop_variable_name here;
END FOR;

How to select all parameter values in SSRS?

I have a parameters #Year and #Month in my report, where month has assigned values like January(label): 1(values), February: 2, ...
My datased is feeded by stored procedure which has a filter
WHERE (cal.CalendarYear = #Year) AND (cal.MonthId = #Month)
When I check 'Allow multiply values' in parameter settings, it returns an error
Error converting data type nvarchar into int.
How can I select all values (by default)?
If you don't need to use a Stored Proc you can easily solve the problem.
Copy the SQL from your stored proc (excluding the PROC definition, just the main code) and paste it in as your dataset query.
Change your = #Year and = #Month to IN(#Year) and IN(#Month)
That's all there is to it, no joining, splitting or anything else.
SSRS will inject the parameter values as comma separated values correctly for you.
When you select multiple values, you pass the parameter to the procedure as an expression with Join().
Then in your procedure change your month parameter to be of type nvarchar(max).
Create a temp table and use a t-sql split string function (Google this, there are so many varieties but if you're stuck we can find one) to split the string into a table. Then inner join to your table in your procedure to filter on the selections.
Your error message about "nvarchar into int" suggests a data type mismatch between your SSRS parameter and your MonthId column. Check the Report Parameter Properties -> General -> Data type for the former and your table schema for the latter, and make sure they're either both text/varchar or both integers.
Allowing your query to handle multiple parameter values should be much simpler than needing to use joins and splits. Just use IN instead of =, and put your parameter name inside a set of brackets.
AND (cal.MonthId IN (#Month))
To set the defaults for your parameter, go to the Report Parameter Properties -> Default Values. Select the Specify values option, and add your numbers 1-12 as separate Value records.

Return two values from a scalar SQL Function

I have a Scalar SQL function thats returns a decimal value, and this function is used in many stored procedures across my database. Now in some procedures, I need to set a value based on some criteria inside the function. To make it clearer, depending on some variables used in calculating the result of the function, I want to set another variable inside the Stored procedure, and return it to the client.
I don't want to change how the result is returned or the return type of the function. I am thinking of doing it by inserting the new value i want into an sql table and then reading it from the procedure, But is there another or better way to do it?
Thanks
No, you cannot. Functions are severely limited in SQL Server and do not allow any side effects.
What you can do, however, is convert your scalar function into a table function. In it, you can return a table with as many columns as you need, so returning more than one value is not a problem.
You have a couple of options
1) Change it from a function to a stored procedure, and add an output parameter.
2) Change it from a scalar function to a table valued function returning a single row, with the additional value as an additional column.
If you need to preserve the existing function signature then just create a new table valued function that does the work (As per option 2 above), and modify your existing function to select from the new table valued function.
Here is some example code demonstrating this:
-- the original scalar function
CREATE FUNCTION dbo.t1(#param1 INT)
RETURNS INT AS
BEGIN
RETURN #param1 + 1
END
GO
-- a new table valued function, that returns 2 values in a single row
CREATE FUNCTION dbo.t2(#param1 INT)
RETURNS TABLE AS
RETURN (SELECT #param1 + 1 AS [r1], #param1 + 2 AS [r2])
GO
-- the modified original function, now selecting from the new table valued function
CREATE FUNCTION dbo.t3(#param1 INT)
RETURNS INT AS
BEGIN
RETURN (SELECT r1 FROM dbo.t2(#param1))
END
GO
-- example usage
SELECT dbo.t1(1)
SELECT * FROM dbo.t2(1)
SELECT dbo.t3(1)
Table value functions that return a single row are my favorite technique when a single answer from a scalar function just isn't adequate (or slows the query too much). A table can have from zero to many rows. Once I realized a 'table' value function can be limited to returning only one row it became obvious that multiple questions that would require separate scalar functions can be accomplished in a single table value function. It's like a scalar function on steroids. I like to read in all needed data just once into an internal table variable, then manipulate that data assigning it to additional variables as needed, finally assembling the answers for the output 'table' of one record. My database environment is read only, not transaction based. Incredibly useful for large (Mult-TB) historical database like medical information. Frequently used to concatenate fields into an end user friendly 'sentence' to deal with data that can have zero to many values, like patient diagnosis. Outer Apply the table value function on filtered data and it is extremely efficient.

Passing a multi-select input parameter as a dataset parameter with IN condition - SSRS

I have a report with an input parameter P_Region that allows the user to select 1-* options. I then need to pass the results of this parameter to a DataSet query. It works if i only select one option but not if i select two.
What i have:
The DataSet parameter for it is set to:
=join(Parameters!P_Region.Value, ",")
The query is:
WHERE ... AND D.City IN(#P_Region)
I have trieda few different things with no luck as well:
=Split(Parameters!Item.Value, ",")
=Split(Join(Parameters!#ReportParameter1.Value,","),",")
WHERE D.Region IN (SELECT * FROM dbo.split(#Department)) with no luck.
Any help is much appreciated!
Solution: (Sorry I feel like this is a pretty easy solution but I did not see it anywhere online and I'm super new with SSRS)
Right click on the dataset
Go to the Parameters tab and set the query parameter back to the default value (No Joins or Splits)
Go to the Filters tab and add the expression of the field you want to be in the parameter, choose the operator "In" and set the value as [#<'Parameter Name'>']
Note: Understand that the other records will still be returned by the query but they will just be filtered. If you are returning large sets of data and using very little of it, this may not be the best route to go.
I think you where on the right track with WHERE D.Region IN (SELECT * FROM dbo.split(#Department)) with no luck.
I use a tabled valued function to create a filter table and parse the values there.
WHERE D.Region IN (SELECT ID FROM dbo.CreateIntIDTable(#Department))
ALTER FUNCTION [dbo].[CreateIntIDTable](#IDList NVARCHAR(3000))
RETURNS #T TABLE (ID INT)
AS BEGIN
WHILE(CHARINDEX(',',#IDList)>0)BEGIN
INSERT INTO #T
SELECT LTRIM(RTRIM(SUBSTRING(#IDList,1,CHARINDEX(',',#IDList)-1)))
SET #IDList = SUBSTRING(#IDList,CHARINDEX(',',#IDList)+LEN(','),LEN(#IDList))
END
INSERT INTO #T SELECT LTRIM(RTRIM(#IDList))
RETURN
END
Try to Create separate dataset for your selection dropdown then you can use your where condition.
for ex.
1) Data set (SELECT Company FROM Companymaster ORDER BY Company)
2) where
company in (#CompanyName)
Did you set up the parameter properties to accept multiple values ?
you don't need to do any Join or Split function if properties ar set up properly.

Checking for a string within a string, and not in another string using SQL

I am trying to build a short SQL script that will check if #NewProductAdded is somewhere in #NewTotalProducts. And also if #NewProductAdded is NOT in #OldTotalProducts. Please have a look at the setup below (The real data is in tables, not variables, but a simple example is all I need):
declare #NewProductAdded as varchar(max)
declare #NewTotalProducts as varchar(max)
declare #OldTotalProducts as varchar(max)
set #NewProductAdded ='ProductB'
set #NewTotalProducts = 'ProductAProductBProductC'
set #OldTotalProducts = 'ProductAProductC'
SELECT CustomerID FROM Products WHERE NewProductAdded ...
I want to make sure that 'ProductB' is contained somewhere within #NewTotalProducts, and is NOT contained anywhere within #OldTotalProducts. Product names vary vastly with thousands of combinations, and there is no way to really separate them from each other in a string. I am sure there is a simple solution or function for this, I just don't know it yet.
The specific answer to your question is like (or charindex() if you are using SQL Server or Sybase):
where #NewTotalProducts like '%'+#NewProductAdded+'%' and
#OldTotalProducts not like '%'+#NewProductAdded+'%'
First comment. If you have to use lists stored in strings, at least use delimiters:
where ','+#NewTotalProducts+',' like '%,'+#NewProductAdded+',%' and
','+#OldTotalProducts+',' not like '%,'+#NewProductAdded+',%'
Second comment. Don't store lists in strings. Instead, use a temporary tables or table variable:
declare #NewTotalProducts table (name varchar(255));
insert into #NewTotalProducts(name)
select 'ProductA' union all
select 'ProductB' . . .
Note: throughout this answer I have used SQL Server syntax. The code appears to be SQL Server.