Differences between select #var=column1 from table1 & select top 1 column1 from table1 - sql-server-2005

In sql server 2005
differences between select #var=column1 from table1 & select top 1 column1 from table1
I have a problem with a view that has a column in select statement at this model
select column0, fn(column0) as col from table2
that fn return select #var=column1 from table1 where table1.column3=#inputid
I replace it with this
select
column0,
(select top 1 column1 from table1 where table1.id = table2.column0) as col
from table2
but result is not same as previous
and using order by in
select top 1 column1 from table1 where table1.id = table2.column0
has no effect too
I need to know why can I change
select top 1 column1 from table1 where table1.id = table2.column0
that has same result as
select #var=column1 from table1 where table1.column3 = #inputid

When Sql Server compiles a query, It doesn't compiles Scalar valued function. So you can never know which result will come from Table valued function. Moreover scalar valued function results in relatively bad performance when compared to inline query or table valued functions.
Since ORDER BY gets executed after TOP in case of UNION. So I doubt this case is getting applied. Can you paste the execution plan of query
Order of execution of query
1. FROM, JOIN, APPLY and ON
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. ORDER BY
7. TOP
8. FOR XML
When using UNION, Order of execution changes slightly
1. FROM, JOIN, APPLY and ON
2. WHERE
3. GROUP BY
4. HAVING
5. TOP
5. UNION and SELECT
6. ORDER BY
8. FOR XML

Related

Using distinct on in subqueries

I noticed that in PostgreSQL the following two queries output different results:
select a.*
from (
select distinct on (t1.col1)
t1.*
from t1
order by t1.col1, t1.col2
) a
where a.col3 = value
;
create table temp as
select distinct on (t1.col1)
t1.*
from t1
order by t1.col1, t1.col2
;
select temp.*
from temp
where temp.col3 = value
;
I guess it has something to do with using distinct on in subqueries.
What is the correct way to use distinct on in subqueries? E.g. can I use it if I don't use where statement?
Or in queries like
(
select distinct on (a.col1)
a.*
from a
)
union
(
select distinct on (b.col1)
b.*
from b
)
In normal situation, both examples should return the same result.
I suspect that you are getting different results because the order by clause of your distinct on subquery is not deterministic. That is, there may be several rows in t1 sharing the same col1 and col2.
If the columns in the order by do not uniquely identify each row, then the database has to make its own decision about which row will be retained in the resultset: as a consequence, the results are not stable, meaning that consecutive executions of the same query may yield different results.
Make sure that your order by clause is deterministic (for example by adding more columns in the clause), and this problem should not arise anymore.

Using a value from one query in second query sql

SELECT AS, COUNT(*)
FROM Table1
HAVING COUNT(AS)>1
group BY AS;
This produces the result
AS COUNT
5 2
I then want to use the AS value in another query and only output the end result. Is this possible.i was thinking something like.
SELECT *
FROM
TABLE 2
Where AS =(
SELECT AS, COUNT(*)
FROM Table1
HAVING COUNT(AS)>1
group BY AS;
);
This is called a subquery. To be safe, you would use in instead of = (and as is a bad name for a column, because it is a SQL key word):
SELECT *
FROM TABLE2
WHERE col IN (SELECT col
FROM Table1
GROUP BY col
HAVING COUNT(col) > 1
);
Your first query is also incorrect, because the having clause goes after the group by.
You could use a subquery with the in operator:
SELECT *
FROM table2
WHERE AS IN (SELECT AS
FROM table1
GROUP BY AS
HAVING COUNT(*) > 1)

Wrapping SQL query into outer Select causes Order By reshuffle

I have an engine that builds a query. So this is not static and this is why I had to go this way (below). Plus, it works for SQL and Oracle (Oracle adds different wrapper, RowNum, etc...). I have no easy way to test Oracle but below is SQL Server problem, step-by-step logic
Lets take a simple query
Select field1 as f1, myDate dateFld From table1 t1 Where t1.field2 = 1
I may or may not, have to union output with another table
Select field1, myDate dateFld as f1 From table1 t1 Where t1.field2 = 1
Union
Select field2, myDate dateFld as f1 From table2 t2 Where t2.field2 = 2
I need to get only N records from this Union
Select Top(N) *
From
(
Select field1 as f1, myDate dateFld From table1 t1 Where t1.field2 = 1
Union
Select field2 as f1, myDate dateFld From table2 t2 Where t2.field2 = 2
) Union_Tbl_Alias
Order By dateFld Desc, f1
Remember this "Order by"
I also have Select Subqueries (and nothing I can do but have them in Select), which I moved to yet another Select wrapper
Select
f1,
myDate,
(Select field99 From table99 t99 Where t99.f1 = Outer_Tbl_Alias.f1) as f3
From
(
Select Top(N) *
From
(
Select field1 as f1, myDate dateFld From table1 t1 Where t1.field2 = 1
Union
Select field2 as f1, myDate dateFld From table2 t2 Where t2.field2 = 2
)
Order By dateFld Desc, f1
) Outer_Tbl_Alias
So the problem is that outer-most select reshuffles records a bit. They no longer sorted dateFld Desc.
I don't want to speculate, I think, this is only SQL Server issue but I will test it in oracle as well. Moving "Order By" to outer-most statement fixes it for SQL Server.
But I'm wondering:
1 - why it happens?
2 - is there a hint to tell SQL server - keep the order of inner Select?
That behavior appears to make sense. Your outer query does not contain an ORDER BY clause so the order of the results is arbitrary. The fact that rows may have been ordered in a subquery is not controlling (though it undoubtedly does end up affecting the order of the results). Since you are building the query programmatically, it would make far more sense to add whatever ORDER BY clause you want than to try to work around the issue (and I'm not aware of a way to work around the issue that is guaranteed to work every time).
You'll have exactly the same issue when you run against an Oracle database and switch out the TOP for a couple of nested queries with rownum predicates. The only way to guarantee the order of your results is to add an ORDER BY clause. Since that is going to be necessary regardless of the database you are using, it makes even more sense to do it correctly by adding the additional ORDER BY to the outer query rather than having different database-specific workarounds.

UNION ALL vs OR condition in sql server query

I have to select some rows based on a not exists condition on a table. If I use a union all as below, it gets executed in less than 1 second.
SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(
SELECT 1 FROM TABLE t
WHERE Data1 = t.Col1 AND Data2=t.Col2
UNION ALL
SELECT 1 FROM TABLE t
WHERE Data1 = t.Col2 AND Data2=t.Col1
)
but if I use an OR condition, it takes close to a minute as SQL server is doing a table lazy pool. Can someone explain it?
SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(
SELECT 1 FROM TABLE t
WHERE ( (Data1 = t.Col1 AND Data2=t.Col2) OR (Data1 = t.Col2 AND Data2=t.Col1))
)
The issue is that you are specifying two conditions with OR that apply to separate tables in your query. Because of this, the nonclustered index seek has to return most or all of the rows in your big table because OR logic means they might also match the condition clause in the second table.
Look at the SQL execution plan in all three examples above, and notice the number of rows that come out of the nonclustered index seek from the big table. The ultimate result may only return 1,000 or fewer of the 800,000 rows in the table but the OR clause means that the contents of that table have to be cross-referenced with the conditional in the second table since OR means they may be needed for the final query output.
Depending on your execution plan, the index seek may pull out all 800,000 rows in big table because they may also match the conditions of the OR clause in the second table. The UNION ALL is two separate query against one table each, so the index seek only has to output the smaller result set that might match the condition for that query.
I hope this makes sense. I've run across the same situation while refactoring slow-running SQL statements.
Cheers,
Andre Ranieri
The query plan is also affected by the number of rows in your tables. How many rows are there in table t ?
You could also try:
SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(
SELECT 1 FROM TABLE t
WHERE Data1 = t.Col1 AND Data2=t.Col2
)
AND NOT EXISTS
(
SELECT 1 FROM TABLE t
WHERE Data1 = t.Col2 AND Data2=t.Col1
)
or (corrected for SQL-Server) this that will use the index:
WITH tt AS <---- a temp table with 2 rows
( SELECT Data1 AS Col1, Data2 AS Col2
UNION
SELECT Data2 AS Col1, Data1 AS Col2
)
SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(
SELECT 1
FROM TABLE t
JOIN tt
ON tt.Col1 = t.Col1 AND tt.Col2=t.Col2
)
The usage of the OR is probably causing the query optimizer to no longer use an index in the second query. Look at the explain for each query and that will tell you the answer.

SQL Server Count Query with no order

I have a series of select count queries tied together by UNION egg
Select Count(Column1) From Table1 where Table1 column1 = 1
union
Select Count(Column2) From Table1 where Table1 column2 = 1
It works fine but it just orders in asc or desc order but I want it to go in order by which I requested, I want the first query to always be first in the result no matter what the value is. Thanks for any help.
Run two queries?
You can add a column and sort on it
Select 1 as sequence, Count(Column1) From Table1 where Table1 column1 = 1
union
Select 2 as sequence, Count(Column2) From Table1 where Table1 column2 = 1
ORDER BY sequence
Try this:
SELECT COUNT(*) AS cnt, 1 AS SortOrder FROM Table1 WHERE column1 = 1
UNION ALL
SELECT COUNT(*) AS cnt, 2 AS SortOrder FROM Table1 WHERE column2 = 1
ORDER BY SortOrder
The main change I have made is to add a column which you can use to ORDER BY. Some of the other changes I have made:
You don't mean UNION, you mean UNION ALL. Otherwise with your query if the counts were the same you'd only get one row. In the new query this wouldn't happen, but you should still use UNION ALL because that's semantically what you mean.
Writing COUNT(column1) is unnecessary because your WHERE clause guarantees that column1 can never be NULL. Use COUNT(*). I imagine that even if you write COUNT(column1) most databases will see that column1 cannot be NULL and omit the unnecessary NULL check, but again there is nothing wrong with being explicit - you want to count all rows and COUNT(*) makes that clear.
You shouldn't have Table1 column1 with a space between. There should be a dot. Or simply omit the table name as it is not required here.