Different output when executing statement directly and from stored procedure? - sql-server

Sql Server 2008 is behaving in a strange way. When I execute the stored procedure the out put is in a different order than when I execute the statements directly for the same parameters. I am not sure what I am doing wrong. Please help!!!
Here is a simple query structure and explain what it does.
Top 10 Query1
Union all
Top 10 Query2
Order by name
a. When u run it in a proc :
From Query 1 it fetches top 10 , then from query 2 it fetches top 10 and then finally it does the order
b. When you open the query :
From Query 1 it applies the order and then fetches top 10, and from Query 2 it also applies the order and then fetches top 10
This is strange that it's doing 2 different things with the same query.
Output from Procedure
Name Cost Price
A2 Bag Stickerss DO NOT STOCKTAKES 24
aaaaaa 5
aaaaaa 7.5
Output from Query
Name Cost Price
A2 Bag Stickerss DO NOT STOCKTAKES 24
A2 Bag Stickerss DO NOT STOCKTAKES 27
aaaaaa 5
aaaaaa 7.5
aaaaaa 9

TOP without ORDER BY is not deterministic.
It just means "Select any 10 records". So you are selecting an arbitrary set of 10 results from query 1 and an arbitrary set of 10 records from query 2 then ordering these 20 records by name.
Which TOP 10 you end up with depends on the plan chosen (which may well be different in the stored procedure) You would need to add an order by (on a set of columns with no ties) to each query to make it deterministic.
Your current query is like
SELECT TOP 10 *
FROM master..spt_values
UNION ALL
SELECT TOP 10 *
FROM master..spt_values
ORDER BY name
You see that SQL Server just adds a TOP iterator to both branches of the plan to limit the output of both queries then these feed into the Union and the sort by name happens after that. SQL Server chose a clustered index scan for this so the results will likely be the TOP 10 in clustered index order type,number,name (though this shouldn't be relied upon either, without a specified order by to indicate what the TOP refers to any set of 10 rows would be valid. It would be perfectly valid for it to use the advanced scanning feature here and give you an arbitrary 10 rows that it knows to be in cache as they have just been read by an other query's scan.)
To rewrite the query with TOP...ORDER BY specified for each element you could use CTEs as below.
;WITH Query1 AS
(
SELECT TOP 10 *
FROM master..spt_values
ORDER BY name,number,type
), Query2 AS
(
SELECT TOP 10 *
FROM master..spt_values
ORDER BY number,type,name
)
SELECT *
FROM Query1
UNION ALL
SELECT *
FROM Query2
ORDER BY name

Related

tableau custom sql pivot

I have a SQL Server data source that I cannot change the structure of.
I have started pivoting the data with CustomSQL query below, but I need to modify the query so that when iterations 3, 4 ,5 ...n data are added to the source in the future, it automatically includes it in the pivoted data. I don't want to have to keep updating the query. Any ideas?
KPI Name Iteration 1 Iteration 2
a 1 2
b 50 51
Select [KPI]
, 'Iteration1' as [Iteration]
, [Iteration1] as [Count]
From [MC_KPI]
Union ALL
Select [KPI]
, 'Iteration2' as [Iteration]
, [Iteration2] as [Count]
From [KPI]
Now I have this
KPI Name Iteration 1 Iteration 2
a 1 1
a 2 2
b 1 50
b 2 51
What you are doing is called "unpivot" in SQL Server. You can see the description here:
https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-2017
If you want to be able to add iterations without having to modify something in tableau, you can create a view in SQL that does unpivot and just do "select * from view" in tableau. This would give you the chance to change the view under the covers from tableau and have things continue to work (since the unpivot output is just a property bag and the columns are not really changing as you add properties into the output)

SELECT TOP 1 from table value function much slower than selecting all rows

I have a table-valued function that returns four rows:
SELECT *
FROM dbo.GetStuff('0D182B8B-7A80-4D45-8900-23FA01FCFE5A')
ORDER BY TurboEncabulatorID DESC
and this returns quickly (< 1s):
TurboEncabulatorID Trunion Casing StatorSlots
------------------ ------- ------ -----------
4 G Red 19
3 F Pink 24
2 H Maroon 17
1 G Purple 32
But i only want the "last" row (i.e. the row with the highest TurboEncabulatorID). So i add the TOP:
SELECT TOP 1 *
FROM dbo.GetStuff('0D182B8B-7A80-4D45-8900-23FA01FCFE5A')
ORDER BY TurboEncabulatorID DESC
This query takes ~40s to run, with a huge amount of I/O, and a much worse query plan.
Obviously this is an issue with the optimizer - but how can i work around it?
i've updated all statistics
i've rebuilt all indexes
Bonus Reading
Will the OPTIMIZE option work in a multi-statement table function?
OPTIMIZE FOR UNKNOWN – a little known SQL Server 2008 feature
The workaround i came up with, which obviously isn't an answer, is to try to confuse the optimizer:
select top 1 rows
from top 100 percent of rows
from table valued function
In other words:
WITH optimizerWorkaround AS
(
SELECT TOP 1 PERCENT *
FROM dbo.GetStuff('0D182B8B-7A80-4D45-8900-23FA01FCFE5A')
ORDER BY TurboEncabulatorID DESC
)
SELECT TOP 1 *
FROM optimizerWorkaround
ORDER BY TurboEncabulatorID DESC
This returns quickly as if i had no TOP in the first place.

Why is this stored procedure using TOP 100 PERCENT?

I have the following stored procedure inside a third party application inside sql server 2008 R2:-
ALTER PROCEDURE [dbo].[GetContacts]
AS
BEGIN
---------
SELECT TOP (100) PERCENT .....
INTO [#temp200]
FROM dbo.Contact
ORDER BY dbo.Contact.Name
--SELECT * from #temp200
SELECT top 38 *
FROM #temp200
ORDER BY Fullname
delete top (38) FROM #temp200
SELECT top 38 *
FROM #temp200
ORDER BY Fullname
delete top (38) FROM #temp200
SELECT top 38 *
FROM #temp200
ORDER BY Fullname
delete top (38) FROM #temp200
SELECT *
FROM #temp200
ORDER BY Fullname
now I run this inside sql management studio where I got the following results tabs:-
the first one contains 38 records.
the second one 38 records.
the third one contains 38 records.
the fourth one contains 30 records.
where in this case I got 144 records ,, so not sure what is the purpose of the
(SELECT TOP (100)) , as I will get 144 records. now as a test I changed the Select TOP(100) to be Select TOP(35) where in this case I got 2 results; the first on with 38 records while the second one with 17 records and .. so can anyone advice how my above SP is working ?
That guy did not understand that tables do not have order. He tried to insert in an ordered way into the temp tables. This is not possible. The TOP 100 PERCENT trick shuts up the warning about that but does nothing to ensure order.
In earlier SQL Server versions this code might well have worked by coincidence. Since then more optimizations have been added and this code is extremely brittle. Rewrite this if you get the chance. It's a latent time bomb.

Postgresql inner select with distinct

I'm using Postgresql 9.2 and have a simple students table as follow
id | proj_id | mark | name | test_date
I have 2 queries which is described below
select * from (select distinct on (proj_id) proj_id , mark, name,
test_date from students )
t
where t.mark <= 1000
VS
select distinct on (proj_id) proj_id , mark, name, test_date from
students where mark <= 1000
when I run each query for more than 10000 records each query returns different result especially result count although for less than 3000 records the result would be the same.
is this postgresql 9.2 bug or I'm missing something ?
Your queries are producing two different sets of results because they are applying the logic differently.
The first query is getting a distinct set of results, and then applying the 'mark' filter.
The second query is applying the 'mark' filter, and then getting a distinct set of results.
As you don't have any ordering applied the first query could potential return a different number of rows each time it is run - as the mark field could contain any of the values that relate to the proj_id.

How to SELECT LIMIT in ASE 12.5? LIMIT 10, 10 gives syntax error?

How can I LIMIT the result returned by a query in Adaptive Server IQ/12.5.0/0306?
The following gives me a generic error near LIMIT:
SELECT * FROM mytable LIMIT 10, 10;
Any idea why? This is my first time with this dbms
Sybase IQ uses row_count to limit the number of rows returned.
You will have to set the row count at the beginning of your statement and decide whether the statement should be TEMPORARY or not.
ROW_COUNT
SET options
LIMIT statement is not supported in Sybase IQ 12. I think there is not simple or clean solution, similarly like in old SQL server. But there are some approches that works for SQL server 2000 and should work also for Sybase IQ 12. I don't promise that queries below will work on copy&paste.
Subquery
SELECT TOP 10 *
FROM mytable
WHERE Id NOT IN (
SELECT TOP 10 Id FROM mytable ORDER BY OrderingColumn
)
ORDER BY OrderingColumn
Basically, it fetches 10 rows but also skips first 10 rows. To get this works, rows must be unique and ordering is important. Id cannot be more times in results. Otherwise you can filter out valid rows.
Asc-Desc
Another workaround depends on ordering. It uses ordering and fetches 10 rows for second page and you have to take care of last page (it does not work properly with simple formula page * rows per page).
SELECT *
FROM
(
SELECT TOP 10 *
FROM
(
SELECT TOP 20 * -- (page * rows per page)
FROM mytable
ORDER BY Id
) AS t1
ORDER BY Id DESC
) AS t2
ORDER BY Id ASC
I've found some info about non working subqueries in FROM statement in ASE 12. This approach maybe is not possible.
Basic iteration
In this scenario you can just iterate through rows. Let's assume id of tenth row is 15. Then it will select next 10 rows after tenth row. Bad things happen when you will order by another column than Id. It is not possible.
SELECT TOP 10 *
FROM mytable
WHERE Id > 15
ORDER BY Id
Here is article about another workarounds in SQL server 2000. Some should also works in similar ways in Sybase IQ 12.
http://www.codeproject.com/Articles/6936/Paging-of-Large-Resultsets-in-ASP-NET
All those things are workarounds. If you can try to migrate on newer version.

Resources