I have Variable [User::Tablename1] String, I need an Expression that can evaluate at runtime, to check,
If Tablename1 is 'Customer'
select * from dbo.Customer where CustID = 1
Else If Tablename1 is any other tablename
"select * from dbo"**Tablename** where ProdID= 1
My concern is how to make the tablename dynamic and the filter column.
You should create two variables with these texts in the expression for your Select variables:
1: "select * from dbo."+[User::Tablename1]+ "where ProdID= 1"
2: "select * from dbo.Customer where CustID = 1"
Then you can use a sql command text for getting your table names and pass them as a input to a for each loop container to set it to your [User::Tablename1] variable.
In the for each you can use one Expression Task to compare 'Customer' with your [User::Tablename1] value.
At the end, by using the green arrow of the button of expression task, you can set the constraint with the result output. If the result is yes you can execute the Second select, else you execute the first select with any given table name.
Related
I want to select total 450 fixed columns from the table which may or may not have all 450 columns always. When it doesn't have all columns then it should create the missing column and set it's value as null.
In Sql there is a function
if exists()
But in bigquery I am unable to use it wisely.
Any suggestion will help a lot
I assume in the following that you have a source table (the one with potentially "missing" columns) and an existing target table (with the desired schema).
In order to get the information of the columns of these tables, you just need to look into the INFORMATION_SCHEMA.COLUMNS table.
The solution below uses dynamic SQL, to 1) generate the desired SQL, 2) run it.
DECLARE column_selection STRING;
SET column_selection = (
WITH column_table AS (
SELECT
source.column_name AS source_colum,
tgt.column_name AS target_column
FROM
(SELECT
column_name
FROM `<yourproject>.<target_dataset>.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name='<target_table>') tgt
LEFT JOIN
(SELECT column_name
FROM `<yourproject>.<source_dataset>.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name='<source_table>') source
ON source.column_name = tgt.column_name
)
SELECT STRING_AGG(coalesce(source_column,
CONCAT("NULL AS `",target_column, "`")), ", \n") AS col_selection
FROM
column_table
)
EXECUTE IMMEDIATE
FORMAT("SELECT %s FROM `<yourproject>.<source_dataset>.<source_table>`", column_selection) ;
Explanation of the steps
Build a column_table for the columns we want to query:
a. first column containing the columns of the target table,
b. second one containing the corresponding source columns if they exist, or NULL if they don't
Once we have this table, we can build the desired SELECT statement: the name of the column is it's in the source table, or if it's NOT present, we want to have in our query " NULL AS `column_name_in_target` "
This is expressed in the
coalesce(source_column, CONCAT("NULL AS ``",target_column, "\``"))
We aggregate all these statement with STRING_AGG into the desired column selection.
Final step: putting together the rest of the query ( "SELECT" + <column_selection_string> + "FROM <your_source_table>" + ...), and we can EXECUTE IMMEDIATE it.
I have a stored procedure for the Filters of products in my website which goes like:
ALTER PROCEDURE [dbo].[sp_product_get_by_filters]
(#brand_names nvarchar(max),
#type nvarchar(max))
AS
BEGIN
SELECT
tbl_product.product_code,
tbl_product.brand_name,
tbl_product.subcategory_code,
tbl_product.product_name,
tbl_product.product_photo_1,
tbl_product.filter_code,
(select filter_name from tbl_filter where filter_code = tbl_product.filter_code )as filter_name,
(select AVG(CAST(rating AS DECIMAL(10,2))) from tbl_review where product_code = tbl_product.product_code) as Rating,
(select TOP 1 sub_product_price from tbl_sub_product where product_code = tbl_product.product_code) as product_price,
(select TOP 1 size from tbl_sub_product where product_code = tbl_product.product_code) as size,
(select TOP 1 sub_product_code from tbl_sub_product where product_code = tbl_product.product_code) as sub_product_code
FROM
tbl_product
WHERE
tbl_product.brand_name IN (SELECT * FROM dbo.splitstring(#brand_names))
AND tbl_product.filter_code IN (SELECT * FROM dbo.splitstring(#type))
END
#brand_names here is a string of the name of brands separated by comma for example
Apple,Samsung,Nokia
and #type is the filter of the products which is like
'Watch,Mobile,Tablet'
The dbo.splitstring function separates each value from the concatenated string and return the list as a table. So the problem when a User select both Brand Name and Type the query returns the values but if a user select only Brand Name or Type the query doesn't return anything. I want to make the query to return the products if the user select both Brand Name and Type or don't select any of them (You know like filters in every e-commerce website). If the user doesn't select any filter I am passing an empty string in variables like if user doesn't select any brand then #brand_names will be #brand_names = ''.
For example if a user select Brand Name Apple the query must return all the products related to this brand. And again if the user select the Type watch then the query must return the Watches from brand Apple. I am using SQL Server 2008.
Thank you for the Help.
For this kind of "optional parameter" query, an option recompile at the end can improve performance by quite a lot.
If an "unselected" parameter is an empty string, then you can do:
WHERE
(#brand_names = '' or tbl_product.brand_name IN (SELECT * from dbo.splitstring(#brand_names)))
and (#type = '' or tbl_product.filter_code IN (SELECT * from dbo.splitstring(#type)))
option (recompile)
The option (recompile) tells SQL to build a new plan for this statement every time the procedure runs. So, for example, if you pass an empty string for #brand_names, the engine doesn't even need to evaluate the or tbl_product.brand_name in ... part of that predicate. If you don't do this, then SQL will - as always - build a plan for the first execution, and then reuse that plan on subsequent executions. That's not great when different parameter values can make such a big difference to the result.
I have to add a column, a field to multiple views in SQL Server. This is an example of a view that I'm using, where tbxxx stay for a table and vwxxx for a view:
ALTER VIEW [dbo].[vwFornitori_Search]
AS
SELECT IDitem,
IDana,
codice,
ragione_sociale,
c.valore AS colore
FROM tbAnagrafiche
LEFT JOIN tbColori c ON tbAnagrafiche.colore = c.IDcolore
WHERE IDitem = 'FOR'
AND ISNULL(eliminato, 0) = 0
AND ISNULL(obsoleto, 0) = 0
GO
I have to add to all my views another field, another column, that is always the principal table's primary key! The modified view will be:
ALTER VIEW [dbo].[vwFornitori_Search]
AS
SELECT IDitem,
IDana,
codice,
ragione_sociale,
c.valore AS colore,
IDana AS ID
FROM tbAnagrafiche
LEFT JOIN tbColori c ON tbAnagrafiche.colore = c.IDcolore
WHERE IDitem = 'FOR'
AND ISNULL(eliminato, 0) = 0
AND ISNULL(obsoleto, 0) = 0
GO
Usually the primary key has always the same name, like IDana. There's a way to do that with a single script to a list of views ?
You could do this by following these few steps:
1. Extract the SQL of the views' definitions:
SELECT CONCAT(m.definition, ';')
FROM sys.sql_modules m, sys.views v
WHERE m.object_id = v.object_id
AND v.name in ('myview1', 'myview2');
This outputs a list of SQL statements in the form:
CREATE VIEW myview1 (mycol1, mycol2) AS
SELECT ...;
CREATE VIEW myview1 (mycol1, mycol2, mycol3) AS
SELECT ...;
2. Manipulate the SQL
Copy/paste the above output in a text editor and perform an intelligent find/replace to insert the additional column in your select list.
The most simple find/replace would be:
Find: "FROM"
Replace: ", IDana AS ID FROM"
But this will not work if you have nested SELECT statements in your views. In that case you should use regular expressions, if your editor supports them, to make sure the replacement happens exactly where it should.
A regular expression like this would do it:
Find: "/(CREATE VIEW.*?SELECT.*?)FROM/gi"
Replace: "$1, IDana AS ID FROM"
Finally, replace all CREATE VIEW occurrences by ALTER VIEW.
3. Execute the final SQL
Copy/paste the manipulated SQL statements back into your database environment and execute them as a batch.
I have a table with a field name.
For a given name like ABC I want to get the records with that name and the records which have an L appended at the end.
So for ABC I want all records with name either ABC or ABCL.
I tried getting the records using the following code but it doesn't work.
SELECT * FROM tbl
WHERE name like "ABC[|L]"
I am using TSQL.
How can pattern match these names?
Use this SQL:
SELECT * FROM tbl WHERE name IN ('ABC', 'ABCL')
If you are using this SQL within a Stored Procedure / Function, something like following would work. Assuming, you are passing in the value for name in a #name variable.
SELECT * FROM tbl WHERE name IN (#name, #name + 'L')
Use the IN operator.
SELECT *
FROM tbl
WHERE name IN ('ABC', 'ABCL')
In case you will be using variables instead of literal strings, try this:
select *
from tbl
where name like (#YourName + #ExtraLetter)
or name = #YourName
I was writing a SQL script and suddenly got confused at the following line:
IF EXISTS(SELECT #IDTTIC = IDTTIC TOP 1 * FROM #ProblemTickets)
where #ProblemTickets is my table variable.
Is the above condition well written or should it be like this:
IF EXISTS(SELECT TOP 1 #IDTTIC = IDTTIC FROM #ProbelmTickets)
IF EXISTS(SELECT * FROM #ProblemTickets)
BEGIN
SELECT TOP 1 #IDTTIC = IDTTIC FROM #ProblemTickets
END
The Exists Clause check for exisitance of something, if it does exist it will return true and if it doesnt it will return false but you cant return data inside the Exists clause.
You can try like I have shown above
1- Check for existance of something 1st.
2- If it exists then get the top 1 value in your variable.
*Suggestion by Aaron Bertrand *
You can simply assign a value to your variable without checking for existence 1st, If there is any data in the table the value will be assigned to the variable otherwise variable remains NULL.
When assigning value to a variable in a SELECT statement make sure your SELECT is returning only one row back if which obviously you are already doing SELECT TOP 1 but to get the “Right TOP 1” row you should use ORDER BY clause as well.
Also when assigning values to variable in SELECT you cannot retrieve data at the same time, If SELECT is returning more than one column all the values retuned should be stored in a variable
Something like this ..
SELECT TOP 1 #Var1 = Col1, #Var2 = Col2, #Var3 = Col3
FROM TABLE_Name
ORDER BY Some_Column
You Cannot do something like this
SELECT TOP 1 #Var1 = Col1, #Var2 = Col2, Col3
FROM TABLE_Name
ORDER BY Some_Column
Personally, I think it should just be:
SELECT TOP (1) #IDTTIC = IDTTIC FROM #ProblemTickets ORDER BY <something>;
If there are any rows in the table, the value will be populated (unless that column can be NULL, of course). If there are no rows, the variable will still be NULL.
There is no need to say IF EXISTS and then assign the variable with another SELECT. You are just reading the table twice instead of once for no good reason.