SQL Select value as (Subquery) - sql-server

This is the query I am trying to get to work, but I'm getting a syntax error.
SELECT Column1 as (SELECT Value2 from Table2 Where ConditionA, ConditionB, ConditionC)
from Table1
I am self taught, and haven't found anything that says explicitly that this can't be done, but if that is the case then thanks for the closure.

You cannot use the value returned from a subquery for an alias, there is no way to make that work.
Your only option is to build the sql dynamically, and use sp_executesql, but thats usually an indication something else has gone wrong!
Start by getting the value you want, a couple of points
ensure you only get 1 result, either using TOP 1 or appropriate filter conditions
multiple conditions are separated with AND or OR, not a comma
declare #alias NVARCHAR(100) -- whatever is appropriate
SELECT TOP 1 #alias = value2 FROM Table2
WHERE someField = 'some value'
Then build up the sql dynamically, and execute it.
DECLARE #sql NVARCHAR(100) = 'SELECT Column1 AS ' + #alias + ' FROM Table1'
EXEC sp_executesql #sql
You can see this in action here: http://sqlfiddle.com/#!3/71f8d6/3
But, I stress, this is a bad solution.

try
SELECT (SELECT Value2 from Table2 Where ConditionA, ConditionB, ConditionC) Column1 from Table1

Related

Set where clause basis parameter value in SQL Server

I wish to set a condition while making use of the WHERE clause basis #USER_ID input recorded from the user in my SQL server query, but I guess I am missing something essential here.
DECLARE #USER_ID NVARCHAR(255) = 'a,b,c' -- will be multi-select parameter; can be null as well
select * from <table_name>
{
if: #USER_ID is NULL then no WHERE condition
else: WHERE <table_name>.<col_name> in (SELECT item FROM SplitString(#USER_ID,','))
}
Can someone please help here?
Personally, I would suggest switching to a table type parameter, then you don't need to use STRING_SPLIT at all. I'm not going to cover the creation of said type of parameter here though; there's plenty already out there and the documentation is more than enough to explain it too.
As for the problem, if we were to be using STRING_SPLIT you would use a method like below:
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
WHERE YT.YourColumn IN (SELECT SS.Value
FROM STRING_SPLIT(#USER_ID,',') SS)
OR #USER_ID IS NULL
OPTION (RECOMPILE);
The RECOMPILE in the OPTION clause is important, as a query where #USER_ID has the value NULL is likely to be very different to that where it isn't.
You could use a dynamic SQL approach, but for one parameter, I doubt there will more anything more than a negligible benefit. Using the above is much easier for others to understand as well, and the cost of generating the plan every time the query is run should be tiny for such a simple query.
Using a table type parameter, it would actually likely be more performant (assuming you have a useable index on YourColumn) to use a UNION ALL query like the below:
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
JOIN #Users U ON YT.YourColumn = U.UserId
UNION ALL
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
WHERE NOT EXISTS (SELECT 1 FROM #Users U);
You could avoid using STRING_SPLIT entirely here:
WHERE ',' + #USER_ID + ',' LIKE '%,' + <table_name>.<col_name> + ',%'
If the #UserID is NULL, then the condition (1=1) is executed, this is always true. If the #UserID is not NULL, then the OR condition is executed in which all <col_name> in (a, b, c) are present.
SELECT *
FROM <table_name>
WHERE (1=1)
AND ((#USER_ID IS NULL AND (1=1)) -- always true
OR (<table_name>.<col_name> in (SELECT [value] FROM SplitString(#USER_ID,',')))
)

If clause in sql

Declare #a varchar(100);
If #a = select productname from product
The above mentioned query is throwing error as my sql query (select product name from product) is returning multiple values.
Can someone help me with this?
Try something like:
Declare #a varchar(100);
SELECT #a = 'MyProduct'
Then either
If #a = select TOP 1 productname from product ORDER BY <some field>
OR
If #a IN (select productname from product)
However, how do you know which product(s) to match to; you might need a WHERE clause. Some sample data and desired results would help.
Please note that you need to put the SELECT query inside the parenthesis in this case! Also you should note that your select query, in this case should not return more than one value. So to resolve these you need to write it as:
Declare #a varchar(100);
If #a = (select TOP 1 productname from product)
However your query logically seems to be invalid and you should rethink about it, for example you need to say that, you are going to check #a with which product? You might need to add some filters to query and/or add ELSE to your if, etc.
You might also need to read the #PeterSmith's answer too(Using IN...)

select value into variable and alias in SQL Server

I'd like to simultaneously do two things in an MSSQL query:
select a field's value into a variable
select #myvar = colName from tableName
alias my column
select colName as [myCol] from tableName
I've tried these things:
Attempted Syntax select #myvar = colName as [myCol] from tableName
Attempted Syntax select #myvar = (colName as [myCol]) from tableName
Attempted Syntax select (#myvar = colName) as [myCol] from tableName
checked select statement syntax: https://msdn.microsoft.com/en-us/library/ms176104.aspx
If this is possible, how can it be accomplished?
A select can either assign values to variables or return column values, but not both.
In some cases, e.g. when using select to provide data to an insert, an output clause may be useful. A tool well worth having in your pocket as it provides access to identity values from insert and both before and after values when used with update.

Using parameterised column filter and column sort direction

If I have a stored procedure which takes the following parameters:
#orderByColumn
#sortDir
#columnName
#filter
How can I have the stored procedure order by the specific #orderByColumn and #sortDir parameters?
In addition, what about having a WHERE clause and using the #columnName parameter and the #filter parameter?
I would not want to do any dynamic SQL concatenation if it can be avoided.
So for example, I was thinking something like the following:
SELECT
[col1], [col2], [col3]
FROM
[myTable]
WHERE
#columnName = #filter
ORDER BY
#orderByColumn #sortDIR
but of course, that is not the right way.
Many thanks!
When the optimizer creates a query plan, it can vary the values used, but it has to know the tables and ordering. So column and table names cannot be parameterized.
You can either use dynamic SQL:
declare #sql nvarchar(max)
set #sql = 'select * from dbo.YourTable order by ' + #orderByColumn
Or use some trickery so a value, not a column name, determines the sort order:
select *
from dbo.YourTable
order by
case #orderByColumn
when 'col1' then col1
when 'col2' then col2
when 'col3' then col3
end
In my experience, you'll get the most sane code by generating the SQL queries client-side. T-SQL is not ideal for string manipulation.

In SQL Server, is there a way to avoid using a Cursor?

I have a table where each record has a Table_Name (name of a table). I then use a Cursor to select all table names related to some record in to a Cursor. Then I do a WHILE for each table name in the Cursor to do some job.
I want to know if it's possible to solve this problem without using a Cursor.
DECLARE tables_cursor CURSOR FAST_FORWARD FOR SELECT Table_Name FROM Some_Table WHERE ...
FETCH NEXT FROM tables_cursor INTO #Dynamic_Table_Name
WHILE ##FETCH_STATUS = 0
BEGIN
...
END
Foreach table name in the cursor I do a dynamic SQL query like this:
SELECT #sql = '
UPDATE dbo.' + #Dynamic_Table_Name + '
SET ...'
EXEC sp_executesql #sql, #params, ...
My question is this: Is it possible to avoid using Cursor to solve this problem?
Unfortunately the design of having table name to reference a table can't be changed, of which I would have done immediately if I could.
yes, you can solve this problem without using cursor. Instead you need to introduce the new table which stores the table name from actual table along with auto generated id column.
Check out the below sample query
declare #test table (id int identity,tableName varchar(20))
insert into #test
select 'abc' union all
select '123' union all
select '345' union all
select 'sdf' union all
select 'uhyi'
instead above query, you can use your query to populate the table variable
insert into #test
SELECT Table_Name FROM Some_Table WHERE ...
And
--select * from #test
declare #cnt int
declare #incr int
select #cnt = count(id) from #test
set #incr = 1
while (#incr <= #cnt)
begin
select tableName from #test where id = #incr
set #incr =#incr + 1
end
Yes, you could avoid the cursor, but you can't avoid the dynamic queries.
You could possibly make a query that returns all the dynamic queries concatenated together as a single string. That way you could execute them all without using a loop, but that's not really any better...
If you can't change the database design, you are stuck with dynamic queries.
Well, you can hide the use of a cursor by using the (undocumented, but widely-used) MS stored procedure sp_MSforeachdb (Google has lots of examples); but that uses a cursor internally, so if it's a philosophical objection then that doesn't really help.
I don't think there can be a set-based way to do this kind of thing, since each table probably has a different relational structure.

Resources