Issue with SQL "Order by" - sql

I would like to compose a SQL query that for example selects the top 2 values of a sorted table using ORDER BY with a query below, but I'm getting unexpected results
select top 2 * from (select top 100 percent * from events order by dates desc) a ;
let's say for example, if the values of the table were 1,3,4
using
select top 100 percent * from events order by dates desc;
would give me 4,3,1
but with
select top 2 * from (select top 100 percent * from events order by dates desc) a;
I get 1,3 instead of 4,3
I was wondering why is that the case and am I missing something?

use order by in outer query as well
select top 2 * from (select top 100 percent * from events order by dates desc) a order by dates desc

Related

Insert duplicate row in SQL Server view

I was wondering if it was possible in SQL Server 2008 R2 to create a view with only the last column (DateTime DESC), but this last row should be copied in the view again.
So the end result would be a View with two rows with the same data.
The query to select one row is easy:
SELECT TOP 1 *
FROM Reporting
ORDER BY DateTime DESC
or
SELECT TOP 1 *
FROM Reporting
WHERE DateTime IN (SELECT MAX(DateTime)
FROM Reporting)
This returns only one row, but I want to duplicate this row in the view again.
Thanks
The syntax in the above answer is invalid. You are not allowed to have ORDER BY in each data source in the UNION ALL. You can have only one at the final statement. So, this is wrong:
SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC
UNION ALL
SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC
And should be done like this:
SELECT * FROM (SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC)
UNION ALL
SELECT * FROM (SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC);
I will advice using a different approach. Use fake data source and then cross apply.
SELECT SI.*
FROM
(
SELECT 1
UNION ALL
SELECT 2
) DS ([col])
CROSS APPLY
(
SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC
) SI;
You can test easily that the execution plan of this statement is better causing only one ordering and index scan:
Try Union all:
SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC
UNION ALL
SELECT TOP 1 * FROM Reporting ORDER BY DateTime DESC

Select Minimum value of column A where Column B=1

I have this table AVERAGE
I want to
select * from table where VhrNum=MIN(VhrNum) and EmptyOrNot=1
I've Tried this query but it's not working
select *
from Average
where Itmnum='1'
and VhrNum = (
select MIN(VhrNum)
from (
select *
from Average
where EmptyOrNot = '1'
)
)
In my case it's should select the third row
Why not just take the top 1 row and order by by the column?
SELECT TOP 1 *
FROM [table]
WHERE EmptyOrNot=1
ORDER BY VhrNum
Use TOP 1 with ORDER BY
select Top 1 * from table where EmptyOrNot=1
Order by VhrNum ASC
If you more than one record with min VhrNum value and you want all the tie records then use TOP 1 WITH TIES
select Top 1 With Ties * from table where EmptyOrNot=1
Order by VhrNum ASC
You can try like this
SELECT MIN(VhrNum) FROM table_name where EmptyOrNot=1;
Aggregate functions need a GROUP BY - or you could ORDER BY and select the first.
Aggregate won't let you do a SELECT *, which isn't really good practice anyway, and aggregate makes it clearer that you're actually trying to get the MIN of this. TOP 1/ORDER BY would let you do a SELECT *, but may be less immediately clear that all you're really trying to get is the MIN(VhrNum).
Aggregate:
SELECT MIN(VhrNum)
FROM Average
WHERE EmptyOrNot = 1
GROUP BY EmptyOrNot
Top:
SELECT TOP(1) VhrNum, *
FROM Average
WHERE EmptyOrNot = 1
ORDER BY VhrNum ASC
You can try this:
select top 1 * from table where VhrNum= (select min(VhrNum) from table);

Select 2nd and 3rd newest row in an SQL table

i'm currently developing a news-site.
So here is the problem. I want to select the 2nd and 3rd row in a TOP 3.
SELECT TOP 3 * FROM News ORDER BY Date DESC;
I want to remove the 1st row and only return the 2nd and 3rd row.
Can anyone help?
Try this:
SELECT TOP 2 FROM
( SELECT TOP 3 * FROM News ORDER BY Date DESC ) xx
ORDER BY Date
SQLFiddle: http://www.sqlfiddle.com/#!3/dbb7e/5
You can also do this generically using window functions:
select n.*
from (SELECT n.*, row_number() over (order by date desc) as seqnum
FROM News n
) n
where n.seqnum >= 2 and n.seqnum <= 3;
I just offer this as a general solution. You can also ensure that you get everything from the second date (in case there are more than two items on that date) by using dense_rank() rather than row_number().
If you know that no two dates will be the same, you could add
where date not in (select max(date) from News)
Or you could look at rowid if you know that the first item will have rowid=0, for example if you created a temp table with the results of your initial query.
I assume, you somehow know what you Top 3 news are by ordering by date descending.
Therfore you should use the LIMIT clause with an OFFSET [For sqlite]
SELECT * FROM News ORDER BY Date DESC LIMIT 2 OFFSET 1;
Select top 2 * from News cross apply (select top 3 from news order by date desc)x

Select random x of top y records

I need to select 5 records randomly out of the top 100 records sorted by amount.
This can be broken into 2 queries but I do not know how to combine them without creating a function (which I'm thinking might be less efficient.
Query 1: SELECT TOP 100 from Cars order by price desc
Query 2: SELECT TOP 5 * FROM (Query1) ORDER BY NEWID()
I'm just not sure how to combine these, whether using an inner joing or just an inner select?
My first reaction was to try this which does not work:
SELECT TOP 5 * FROM (SELECT TOP 100 * FROM Cars order by Price desc) ORDER BY NEWID()
You need to name your subquery:
SELECT TOP 5 * FROM (SELECT TOP 100 * FROM Cars order by Price desc) [A] ORDER BY NEWID()

sql query to find fifth record

How can i find the fifth record in a table using sql query?
If you are feeling argumentative, consider using "SELECT * FROM table LIMIT 1" and arguing that since SQL does not promise to return results in any particular order, the row returned is spiritually equivalent to the fifth, then show your tattoo: "The nth element of an unordered set is meaningless!"
SELECT TOP 1 * FROM (SELECT TOP 5 * FROM Table T ORDER BY Column ASC) ORDER BY Column Desc
If you are using SqlServer you could use the TOP keyword to achieve this.
select top 1 * from(
select top 5 * from myTable order by orderingColumn) as A
order by orderingColumn desc
If you are using Oracle this should work (however i am not able to test this now)
select *
from (
select *, row_number() over (order by orderingColumn) r
from items
)
where r = 5;
SELECT * FROM table LIMIT 1 OFFSET 4;
Fifth record only in MySQL
SELECT * FROM anytable LIMIT ORDER BY id LIMIT 4,1
For SQL Server (recent-ish incarnations, anyway) something like this should work:
SELECT
*
FROM
(
SELECT
*,
ROW_NUMBER() OVER (ORDER BY the_table.the_column) 'row_num'
FROM
the_table
) numbered_rows
WHERE
row_num = 5
However, I'd actually put my vote with Thomas L Holaday's answer :)