Unexpected SQL Behaviour with "SELECT TOP" Query - sql

I'm using Microsoft SQL Server 2019 and when I execute:
SELECT TOP 10 *
FROM WideWorldImporters.Sales.Invoices
SELECT TOP 10 CustomerID
FROM WideWorldImporters.Sales.Invoices
It gives results:
Which is incorrect because those aren't the "top 10" customer IDs as displayed by the first query.
Full Screenshot:
Edit: The behaviour I expected above matches what actually happens in SQL Sever 2014. I suspect they changed the underlying implementation in SQL Server 2019, although it still satisfies the documented behaviour.

A TOP without ORDER BY is unpredictable. This is documented by Microsoft. From Microsoft docs:
When you use TOP with the ORDER BY clause, the result set is limited to the first N number of ordered rows. Otherwise, TOP returns the first N number of rows in an undefined order.
...
In a SELECT statement, always use an ORDER BY clause with the TOP clause. Because, it's the only way to predictably indicate which rows are affected by TOP.
See also how does SELECT TOP works when no order by is specified?

You have no ORDER BY so the top 10 results by an indeterminate order are returned. This ordering can change, from one execution to the next.
Tables in SQL represent unordered sets. If you want particular rows using TOP, you need to have an ORDER BY.

This is too long for a comment.
In SQL, table records are unordered. For this reason, a query like yours:
SELECT TOP 10 * FROM WideWorldImporters.Sales.Invoices
... will produce inconsistent results, because it is missing an ORDER BY clause. You need to tell your RDBMS which column should be used to order the records so in can define which TOP records should be returned. For example, something like:
SELECT TOP 10 * FROM WideWorldImporters.Sales.Invoices ORDER BY InvoiceID DESC

This result is absolutely normal, as your query doesn't specify an order. The top 10 returns the first 10 results.
If you don't specify any ordering clause, the results will be returned according to the previous operations of the SQL engine, which might not always be the same, and surely not what you expect them to be.

Related

SQL Top clause with order by clause

I am bit new to SQL, I want to write query with TOP clause and order by clause.
So, for returning all the records I write below query
select PatientName,PlanDate as Date,* from OPLMLA21..Exams order
by PlanDate desc
And I need top few elements from same query, so I modified the query to
select top(5) PatientName,PlanDate as Date,* from OPLMLA21..Exams
order by PlanDate desc
In my understanding it will give the top 5 results from the previous query, but I see ambiguity there. I have attached the screen shot of query results .
May be my understanding is wrong, I read a lot but not able to understand this please help me out.
I stated this in a comment, however, to repeat that:
 TOP (5) doesn't give the "top results" of the prior query though, no. It gives the top (first) rows from the dataset defined in the query it in is. If there are multiple rows that have the same "rank", then the row(s) returned for that rank are arbitrary. So, for example, for your query if you have 100 rows all with the same value for PlanDate, what 5 rows you get are completely arbitrary and could be different (including the order they are in) every time you run said query.
What I mean by arbitrary is that, effectively, SQL Server is free to choose whatever rows, of those applicable, are returned. Sometimes this might be the same everytime you run the query, but this by luck more than anything. As your database gets larger, you have more users querying the data, you involve joins, things like locks, indexes, parrallelism, etc all will effect the "order" that SQL Server is processing said data, and will effect an ambigious TOP clause.
Take the example data below:
ID | SomeDate
---|---------
1 |2020-01-01
2 |2020-01-01
3 |2020-01-01
4 |2020-01-01
5 |2020-01-01
6 |2020-01-02
Now, what would you expect if I ran a TOP (2) against that table with an ORDER BY clause of SomeDate DESC. Well, certainly, you'd expect the "last" row (with an ID of 6) to be returned, but what about the next row? The other 5 rows all have the same value for SomeDate. Perhaps, because your under the impression that data in a table is pre-sorted, you might expect the row with a value of 5 for ID. What if I told you that there was a CLUSTERED INDEX on ID ASC; that might well end up meaning that the row with a value of 1 is returned. What if there is also an index on SomeDate DESC?
What if the table was 10,000 of rows in size, and you also have a JOIN to another table, which also has a CLUSTERED INDEX, and some user is performing a query with some specific row locking on in while you run your query? What would you expect then?
Without your ORDER BY being specific enough to ensure that each row has a distinct ordering position, SQL Server will return other rows in an arbitrary order and when mixed with a TOP means the "top" rows will also be arbitrary.
Side note: I note in your image (of what appears to be SSMS), your "dates" are in the format yyyyMMdd. This strongly implies that you are storing a date value as a varchar or int type. This is a design flaw and needs to be fixed. There are 6 date and time data types, and 5 of them are far superior to using a string and numerical data type to storing the data.

TOP 1 and ORDER BY not returning correct results

I have read the other topics on this but they don't seem to match my scenario. I have a query that is ordering the results by Entry Date ASC and then by Sort ASC.
The results shown are correctly ordered, however when I change my query to only pull TOP 1 it returns the second result instead. I have no idea why or how this happens.
If your query has the order by in the outermost select, then the results should be returned in that order. Period.
If the order by is anywhere else -- in a subquery or in a window frame specification -- then the results might look like they are ordered, but the ordering is not guaranteed.
My guess is that you don't have the explicit order by that the query needs to do what you intend.
Also, although not the case with your sample data, if the keys have the same value then they can appear in any order -- and in different positions when you run the query multiple times.

Are big-query results always ordered, that is: using OFFSET makes sense to skip rows?

In other words does a select query order results every time, so these 2 will always produce unique values:
select *
from bigquery-public-data.crypto_ethereum.balances
limit 10 OFFSET 100
select *
from bigquery-public-data.crypto_ethereum.balances
limit 10 OFFSET 2000
Assuming of course the table has unique values...I am just curious if without using "order" clause the table is always deterministic/consequetive or can the results duplicate if they're returned indeed at random? 10x!
I am just curious if without using "order" clause the table is always deterministic/consequetive or can the results duplicate if they're returned indeed at random.
No. SQL tables represent unordered set of rows. There is no inherent ordering of the rows. Unless an order by clause is specified, there is no guarantee that two consequent executive of the same query would yield an indentical result. The database is free to return the rows in whatever order it likes.
As a consequence, the results of a query with a row-limiting clause but no order by clause are not deterministic. Do add an order by clause the these queries, or you will sooner or later run into suprising and hard-to-debug behaviors.

Records issue using top keyword in sql query

I have a Linq query which is working fine but i have noticed when i use take keyword with that query it does not return the same top selected records.
When i saw the Sql profiler query they are totally same excepts just top keyword in that what may be the problem. One more thing i have noticed is when i give a no greater then records in database it works fine with take as well.
I am attaching the query and records attachment
and when I apply top 10 in this query it shows this records
What could be the problem im using Sql Server 2008 R2.
Using TOP keyword without ordering does not guarantee repeatability of resultset.
From here
If a SELECT statement that includes TOP also has an ORDER BY clause,
the rows to be returned are selected from the ordered result set. The
whole result set is built in the specified order and the top n rows in
the ordered result set are returned.
Try forcing the query to order the records by using ORDER BY (or orderby in linq).
The default ordering may differ, try explicitly ordering by a column.

When is LIMIT applied? Will it select all results before limiting?

I'm concerned about the performance of a query such as SELECT * FROM user LIMIT 5 on a very large user table. Will it select all records then limit to 5?
More specifically will the following query select all assetids before limiting...
SELECT * FROM assets WHERE asset_id IN(1,2,3,4,5,6,7,8,9,10) LIMIT 5
I realize it doesn't make sense to include all ids in the IN() clause if I'm limiting but I'd like to know how mysql behaves in this situation.
Thanks.
This depends on your query. See this page for more explanations of how LIMIT is applied:
http://dev.mysql.com/doc/refman/5.0/en/limit-optimization.html
For that specific query, the following would apply:
"As soon as MySQL has sent the required number of rows to the client, it aborts the query unless you are using SQL_CALC_FOUND_ROWS."
Hope that helps.
Your query will have to scan all rows by asset_id column, so you better have an index on it. In my experience, you would always want to set an order by clause also, since the result set will be internally (i.e. order unknown), and you would not know why the returned 5 results were the ones you actually wanted.