Force SQL Server to Evaluate Sub Query First - sql

How can I force SQL Server to Evaluate a sub query first?
My query looks something like:
SELECT ObjectId FROM
(SELECT ObjectId FROM Table Where Id = #Id) T
WHERE fn_LongRunningFunction(T.ObjectId) = 1
I want the outer where clause to evaluate on the result of the inner query. How would I do this without inserting the sub query into a temp table.
When I execute this query SQL evaluates the query as if it where written like:
SELECT ObjectId FROM Table Where Id = #Id AND fn_LongRunningFunction(ObjectId) = 1
which is not what I want.

Why you're even using a sub-query here you could have simply used one query here something like ....
SELECT ObjectId
FROM Table
Where Id = #Id
AND fn_LongRunningFunction(ObjectId) = 1
Note
Using a scalar function in where clause as you have will cause a full table scan, Since sql server has to touch every row in the column and execute the function on ObjectId column values to evaluate if it is equal to 1 or not.
Avoid using any functions in where clauses on column names whenever possible.
for example if you are evaluating a value of a column against a given value do the reverse on the other side of the comparison operator and leave the column alone in where clause, for example if you are looking for values in a table
WHERE ColumnName + 20 < 100
Instead of doing you could do something like
WHERE ColumnName < 100 -20
In first example sql server will have to touch every row and will add 20 to its value to evaluate it against 100 which will cause a table scan.
In 2nd example if sql server has an index on that column it will simply do a seek to see which values are less then 100 -20.

Related

Get the list of result from first sql query and execute second query on the result of list of first query

So, I am working with redshift and SQL for the first time. I have run into this problem due to my limted knowledge of SQL.
I have this first query which return me tables with the columnA. (TableX, TableY... etc)
SELECT tablename
FROM PG_TABLE_DEF
WHERE ("column" = 'columnA');
Also I have this second query which returns me all the rows from the table containig certain value of columnA.
SELECT *
FROM TableX
WHERE columnA='123934'
What I want to achieve is take the result from the first query which is list of tables, and for each table run the second query i.e. get the rows with value of columnA=123934 for each table returned from first query.
What you want to achieve is done using dynamic SQL. Dynamic queries let you run a query from a string.
I am not an Redshit user but to generate the SQL string you need to run you could use the following query:
SELECT 'SELECT * FROM '||tablename ||' WHERE ColumnA= ''123934''; '
FROM PG_TABLE_DEF
WHERE ("column" = 'columnA');
You can try running it manually.

Find Top 1 best matching string in SQL server

I have a table 'MyTable' which has some business logics. This table has a column called Expression which has a string built using other columns.
My query is
Select Value from MyTable where #Parameters_Built like Expression
The variable #Parameters_Built is built from Input parameters by Concatenating all together.
In my current scenario,
#Parameteres_Built='1|2|Computer IT/Game Design & Dev (BS)|0|1011A|1|0|'
Below are the expressions
---------------------
%%|%%|%%|0|%%|%%|0|
---------------------
1|2|%%|0|%%|%%|0|
---------------------
1|%%|%%|0|%%|%%|0|
---------------------
So my above query returns true for all the three rows. But It should return only the second row (Maximum match).
I just don't need a solution with fix for this scenario. It's just a example. I need a solution like choosing the best match. Any idea?
Try:
Select top 1 * from MyTable
where #Parameters_Built like Expression
order by len(Expression)-len(replace(Expression,'%',''))
- this orders the results by the number of non-% characters in expression.
SQLFiddle here.

How to select a sql table's column value by giving column index?

I have table with 3 columns. One is Id, second column is Name and the third one Description. How can I select the value in the Description field by giving the column index, 3?
Thanks in advance
You can't, from plain SQL (other than in the ORDER BY clause, which won't give you the value but will allow you to sort the result set by it).
If you are using another programming language to construct a dynamic query, you could use that to identify the column being selected by its index number.
Alternatively, you could parameterise your query to return a specific column based on a case statement - like so:
select a, b, c, d, e, ...,
case ?
when 1 then a
when 2 then b
when 3 then c
when 4 then d
when 5 then e
...
end as parameterised_column
from ...
The problem with referring to a column by an index number is that, one day, someone may add a column and break your application as the wrong value will be returned.
This principle is enforced in SQL because you can select named columns, or all columns using the * syntax.
This principle is not enforced in programming languages, where you can usually access the column by ordinal in code, but you should consider the principle before deciding to use a statement such as (psuedo code)
value = results[0].column[2].value;
It should be possible. You'd have to query the system tables (which do vary from one version of SQL to another) to get the 3rd (or Nth) column name as a string to form a following query using that column name.
In SQL 2000 the tables you'll need to start with are syscolumns with a join to sysobjects for the table name. Then the rank() function on "Colid" will give you the Nth column and "name" (shockingly) the name of the column. Once you've got that in a variable the following command can return the value, compare to it, order by it or whatever you need.
This is how you can retrieve a Column's name by passing it's index.
Here variable AcID is used as the index of the column.
Below is the code e.g
dim gFld as string
vSqlText1 = "Select * from RecMast where ID = 1000"
vSql1 = New SqlClient.SqlCommand(vSqlText1, cnnRice)
vRs1 = vSql1.ExecuteReader
if vRs1.Read then
gFld = vRs1.GetName(AcID)
msgbox gfld
end if
declare #searchIndex int
set #searchIndex = 3
select Description from tbl_name t where t.Id = #searchIndex

how to filter in sql script to not include any column null

imagine there are 50 columns. I dont wan't any row that includes a null value. Are there any tricky way?
SQL 2005 server
Sorry, not really. All 50 columns have to be checked in one form or another.
Column1 IS NOT NULL AND ... AND Column50 IS NOT NULL
Of course, under these conditions why not disallow NULLs in the first place by having NOT NULL in the table definition
If it's SQL Server 2005+ you can do something like:
SELECT fields
FROM MyTable
WHERE stuff
EXCEPT -- This excludes the below results
SELECT fields
FROM MyTable
WHERE (Col1 + Col2 + Col3....) IS NULL
Adding a null to a value results in a null, so the sum of all your columns will be NULL.
This may need to change based on your data types, but adding NULL to either a char/varchar or a number will result in another NULL.
If you are looking at the values not being null, you can do this in the select statement.
SELECT ISNULL(firstname,''), ISNULL(lastname,'') FROM TABLE WHERE SOMETHING=1
This will replace nulls with string blanks. If you want another value use: ISNULL(firstname,'empty') for example. You can use anything where the word empty is.
I prefer this query
select *
from table
where column1>''
and column2>''
and (column3>'' or column3<'')
Allows sql server to use an index seek if the proper index/es exist. you would have to do the syntext for column 3 for any numeric values that could be negative.

Correct syntax for SQL UPDATE where value to be set is a SELECT

Can someone set me straight on the correct syntax for this statement?
I am trying to update a new field in table rounds with an average of a field in table holes where rounds.id is stored as a foreign key.
UPDATE `rounds` SET drivingDistance_avg_per_hole =
SELECT SUM(holes.drivingDistance)/COUNT(holes.drivingDistance) as avg
FROM `holes`, `rounds`
WHERE holes.drivingDistance != ''
AND holes.round = rounds.id
Sure would appreciate the lesson!
Depends on your database. Standard SQL doesn't have the FROM syntax with UPDATE and some databases don't support it. In that case this ought to work:
UPDATE `rounds` SET drivingDistance_avg_per_hole = (
SELECT SUM(holes.drivingDistance)/COUNT(holes.drivingDistance) as avg
FROM `holes`
WHERE holes.drivingDistance != ''
AND holes.round = rounds.id )
The key points are that the subselect has to be in parentheses, and that you don't want to include the destination table in the subselect because then you're selecting all rows of the table whereas you only care about the rows of holes that match the corresponding row from rounds.