Naming query ouput columns using a separate query T-sql - sql

Im looking for a way to name columns using the top 1 selection from a separate query.
select
case when t.test=1 then 1 else 0 end as select top 1 name from #names,
case when t.test=2 then 1 else 0 end as select top 1 name from #names2
from table t
In this example I want to name then columns by the top selection from several temporary columns. However this does not work. Does anyone have a suggestion on how to make this work?
Thank you in advance,
Philip

The SQL query engine does not evaluate expressions when it expects a column name or alias (any object identifier is expected to be literal).
You can construct your SELECT as a string where you inject the names from subqueries:
declare #stmt nvarchar(max)
set #stmt='
select
case when t.test=1 then 1 else 0 end as ['+(select top 1 name from #names)+'],
case when t.test=2 then 1 else 0 end as ['+(select top 1 name from #names2)+']
from table t'
exec(#stmt)
Security concern
As the word "inject" already implies, this can be vulnerable to injection attacks. Use with caution, and only if you have control over the contents of the #names and #names2 tables - do not use this approach when those tables can contain user input.

Related

Terse syntax to return an empty result set from SQL server

Is there a shorter way to write the following?
-- select empty_result
select t.col
from (select 1 as col) t
where 1 = 0 -- never match
The "original" question follows. This was was modified may times, explicitly in hopes of stopping Y responses as a result of showing a specific use-case; and [rightly] claimed to be a confusing mess.
The use-case is a TSQL query that returns an empty result set in some cases while a 'real' result set in another. In both cases the structure is expected to be the same.
if #foo = 'bar'
-- select real_result
else
-- select empty_result
The question here is then, specifically about creating an empty result set / derived table simply.
One way to do this is as follows. Is there a syntactically 'simpler' method?
-- select empty_result
select t.col
from (select 1 as col) t
where 1 = 0 -- never match
An alternative in this specific MINIMAL IF..ELSE.. CASE, it could be constructed as the following SQL. It is (XY) outside the question scope even though it would function here as the resulting schema is the same in the example above. While it may be a good option elsewhere, it requires a different TSQL flow-control structure. It will also not return the correct result sets if both cases result in a different schema - making it too specific in respect to the title scope.
-- XY alternative specific to MINIMAL CASE shown above
-- select real_result or empty_result with single query
select t.col
from real_data t
where #foo = 'bar'
Yes, there is a 'simpler' / shorter / more terse syntax to returning an empty result set in SQL Server that does not require first creating a derived table.
-- select empty_result
select top 0
1 as col
This is SQL Server specific syntax. There might be other similar forms found in other database implementations.
While not specifically about a shorter empty result set syntax, Ken White provided an approach which avoids duplicating schema if it's identical in both cases. The IF flow-control structure is preserved, as per the original question.
if #foo = 'bar'
-- select real_result
select t.col
from real_table t
else
-- select empty_result
select t.col
from real_table t
where 1 = 0

How to execute two queries based on case condition in sql server

I am trying to execute queries based on condition within single table,here is my query in sql server.
where PATTERN is column name and is set to 0 as default value
I want to display result into only one cell of excel sheet. I linked SQL server and Excel sheet.
IF ([PATTERN] = 1)
BEGIN
SELECT PATTERN,COLOR,SHIFT FROM [DEFECT_RESULTS]
END
ELSE
SELECT MODEL,COLOR FROM [DEFECT_RESULTS]
pattern column is present then still following error is displaying
error: Invalid column name 'PATTERN'.
You need to perform a query in the if condition. SQL doesn't know what table/function you're referring to as it stands.
Something like
if exists (select 1 from DEFECT_RESULTS where PATTERN = 1)
begin
…
Which will do the true side of the if if any row in DEFECT_RESULTS matches. You may need a more specific condition.
declare #pattern int
if (#pattern=1)
begin
SELECT PATTERN,COLOR,SHIFT FROM [DEFECT_RESULTS]
end
else if(#pattern=0)
begin
SELECT MODEL,COLOR FROM [DEFECT_RESULTS]
end
A single query cannot return 2 columns sometimes and 3 columns at other times. Perhaps you just want two queries:
SELECT PATTERN, COLOR, SHIFT
FROM [DEFECT_RESULTS]
WHERE PATTERN = 1;
SELECT MODEL, COLOR
FROM [DEFECT_RESULTS]
WHERE PATTERN = 0;

SQL use intermediate results

I have a column with numbers (float) that I would like to categorize and store a category as integer and as label (string). For now assume that the category is simply defined by the FLOOR(x).
This works:
SELECT salary,
FLOOR(salary) AS category_integer,
CASE WHEN FLOOR(salary) = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM test01
but I was wondering if I could use the intermediate variable 'category_integer' defined in the beginning of my query in a later part, something like this:
SELECT salary,
FLOOR(salary) AS category_integer,
CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM test01
but this is apparently not how SQL works. I've looked into Common table Expressions but got lost there. Is there a way to reuse intermediate variables in an SQL expression?
SQL Fiddle
I must have missed this but I couldn't find related questions so far.
You may resort to common table expressions - basically a query that produces a labelled result set you can refer to in subsequent queries.
Adapted to your example:
with cte as (
select salary
, floor(salary) as category_integer
from test01
)
SELECT salary
, category_integer
, CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM cte
;
Consult the reference for more details: CTE / WITH in pgSQL 9.6.
See it at work in SQL fiddle.
There are pre- and post-selection operations. For example order by and group by are post-selection instructions, distinct for example filters out duplicate results during the selection proces itself and as such duplicate results do not even enter the result set to be ordered or grouped.
When you use AS, you are telling PostgreSQL to take the result and put it in a column named category_integer in the output. You are not actually making a variable here that's available during query execution, as the result is only available after the query executes. As such, you can only do this with subselects where you have the result available as a virtual table in itself, where category_integer is a column in a table rather than a variable.
SELECT category_integer,
CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM (SELECT FLOOR(0) AS category_integer FROM test01) AS test02
https://www.postgresql.org/docs/current/static/queries-select-lists.html
https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-TABLE-ALIASES

How to use case statement to declare a local variable for a subsequent subquery?

Is it possible to declare a local variable depending on the case and then fire a common subquery?
Pseudo code:
SELECT
CASE
WHEN TABLE.TYPE = 'STUDENT' variable = "UNIVERSITY"
WHEN TABLE.TYPE = 'EMPLOYEE' variable = "EMPLOYER"
(Some big query here it has a common joins / groupings but the variable changes)
END AS NAME
FROM TABLE
Looking for a SQL Server solution.
Scenario is like this - I have a query that lists some member information . Now I need to get some addendum data to an existing query - I mean result set won't change . I can actually join but then I have to filter out many things - Does that make sense ? Imagine I was display all the members in the table and someone asks me to show the univeristy name or the employer name . And the biggest problem is a member can have more than one university he attended - same for employer . Isn't joins really bad on performance in this case ? Since there are many one to many stuff . Also please note I finally display only 10 records as part of pagination so I thought I should do a case statement .
DECLARE #variable varchar(10)
SELECT #variable =
CASE
WHEN t.TYPE = 'STUDENT' THEN 'UNIVERSITY'
WHEN t.TYPE = 'EMPLOYEE' THEN 'EMPLOYER'
ELSE 'Undefined'
END
FROM TableName t
MSDN - SELECT #local_variable
If the SELECT statement returns more than one value, the variable is
assigned the last value returned.

Check whether a table contains rows or not sql server 2005

How to Check whether a table contains rows or not sql server 2005?
For what purpose?
Quickest for an IF would be IF EXISTS (SELECT * FROM Table)...
For a result set, SELECT TOP 1 1 FROM Table returns either zero or one rows
For exactly one row with a count (0 or non-zero), SELECT COUNT(*) FROM Table
Also, you can use exists
select case when exists (select 1 from table)
then 'contains rows'
else 'doesnt contain rows'
end
or to check if there are child rows for a particular record :
select * from Table t1
where exists(
select 1 from ChildTable t2
where t1.id = t2.parentid)
or in a procedure
if exists(select 1 from table)
begin
-- do stuff
end
Like Other said you can use something like that:
IF NOT EXISTS (SELECT 1 FROM Table)
BEGIN
--Do Something
END
ELSE
BEGIN
--Do Another Thing
END
FOR the best performance, use specific column name instead of * - for example:
SELECT TOP 1 <columnName>
FROM <tableName>
This is optimal because, instead of returning the whole list of columns, it is returning just one. That can save some time.
Also, returning just first row if there are any values, makes it even faster. Actually you got just one value as the result - if there are any rows, or no value if there is no rows.
If you use the table in distributed manner, which is most probably the case, than transporting just one value from the server to the client is much faster.
You also should choose wisely among all the columns to get data from a column which can take as less resource as possible.
Can't you just count the rows using select count(*) from table (or an indexed column instead of * if speed is important)?
If not then maybe this article can point you in the right direction.
Fast:
SELECT TOP (1) CASE
WHEN **NOT_NULL_COLUMN** IS NULL
THEN 'empty table'
ELSE 'not empty table'
END AS info
FROM **TABLE_NAME**