I have this SQL query:
select top(1)
salary
from
(select top(2) salary
from employee
order by salary desc) as b
order by
salary asc
If I don't utilize as b it will give me an error:
Incorrect syntax near ...
Why is mandatory to use as in this query?
You don't need the as keyword. In fact, I advise using as for column aliases but not for table aliases. So, I would write this as:
select top(1) salary
from (select top(2) salary
from employee
order by salary desc
) b
order by salary asc;
You do need the table alias for the subquery, because SQL Server requires that all subqueries in the from clause be named.
This is TSql syntax. Subquery in FROM must have an alias even it's never used. Oracle for example considers this alias optional.
This is because you have a sub-query that, according to the Transact-SQL documentation on FROM, makes the use of an alias mandatory:
When a derived table, rowset or table-valued function, or operator clause (such as PIVOT or UNPIVOT) is used, the required table_alias at the end of the clause is the associated table name for all columns, including grouping columns, returned.
Note that with derived table the kind of sub-query is intended that you use in your SQL statement:
derived_table
Is a subquery that retrieves rows from the database. derived_table is used as input to the outer query.
Because you are using 'salary' twice. Without an alias the interpreter won't know what 'salary' to order the results by. By using an alias it can discern between employee.salary and b.salary.
A different approach to get the 2nd highest salary... as if you need the 3rd or 4th you're approach would get much more challenging...
SELECT *
FROM (SELECT salary, row_number() over (order by salary desc) rn
FROM employee) E
WHERE rn = 2
You are creating two queries. The first one selects the top 2 salaries from employee. You are calling this list "b". Then you are selecting the top salary from "b".
I have a SQL Server 2014 database. I am building a stored procedure that will return counts across several tables that match certain criteria. At this time, I have the following:
SELECT 'Table1' TableName, COUNT(0) TotalRows FROM dbo.[SomeTable]
UNION ALL
SELECT COUNT(DISTINCT [Name]) AS 'Department' FROM [Department]
UNION ALL
SELECT COUNT(DISTINCT [SubDepartment]) AS 'SubDepartment' FROM [Department]
UNION ALL
SELECT 'Table2' TableName, COUNT(0) TotalRows FROM dbo.[AnotherTable]
When I execute this SQL, I get an error that says:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
If I remove the two lines that begin with SELECT COUNT(... it works just fine. However, I need to get the number of department names and the number of sub-department names. How can I do this while still getting the counts from the other tables?
Thanks!
This is my Query:
select top 60 * from ABC_Sessions (nolock)
where EntryDate > '06-22-2012 23:59:59'
GROUP BY TargetedID
then it gives me this error:
Msg 8120, Level 16, State 1, Line 1 Column 'BI_Sessions.SessionID' is
invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
The * in your query expands to all the columns in your table.
select top 60 TargetedID, SessionID, ...
from ABC_Sessions (nolock)
where EntryDate > '06-22-2012 23:59:59'
GROUP BY TargetedID
As the error message states, it's not valid to select SessionID without an aggregate function (e.g. MAX).
This would work:
select top 60 TargetedID, MAX(SessionID) AS MaxSessionID
from ABC_Sessions (nolock)
where EntryDate > '06-22-2012 23:59:59'
GROUP BY TargetedID
You used star * but not group by columns from abc_sessions table.
Using GROUP BY without any aggregate function looks strange for me.
What would you like to see?
It's a matter of theory: as the error says, you're not allowed to SELECT something that you have not at your disposal.
So, when you use a simple SELECT / FROM / WHERE query, everything you have in your FROM tables is OK for you to select.
But if you use a GROUP BY, you're narrowing your view: anything you don't use in your GROUP BY is discarded (think it twice, it makes no sense to select data from several lines when you explicitly ask to group those lines).
Maybe you're confusing GROUP BY and ORDER BY?
The reason why you are getting this error is because you are not using either sum/average/count/max/min or any similar functions in the select statement of yours. Once you use any of them, you won't get this error. ex :
select top 60 TargetedID, MAX(EntryDate)
from ABC_Sessions (nolock)
where EntryDate > '06-22-2012 23:59:59'
GROUP BY TargetedID
I have a SQL Server query which runs just fine -- until I add a computed column to the SELECT statement. Then I get an odd SQL Server error.
Here's the SQL:
SELECT
outmail_.MessageID_,
CONVERT(VARCHAR(10),outmail_.Created_,120) AS 'Issue',
lyrReportSummaryData.mailed,
lyrReportSummaryData.successes,
COUNT(*) AS 'opens',
COUNT(DISTINCT clicktracking_.MemberID_) AS 'unique_opens',
convert(decimal(3,1),((convert(float,[unique_opens]))/[successes]) * 100) AS 'Rate'
FROM
outmail_
RIGHT JOIN
clicktracking_ ON clicktracking_.MessageID_ = outmail_.MessageID_
RIGHT JOIN
lyrReportSummaryData ON lyrReportSummaryData.id = clicktracking_.MessageID_
GROUP BY
outmail_.MessageID_, CONVERT(VARCHAR(10), outmail_.Created_,120),
lyrReportSummaryData.mailed, lyrReportSummaryData.successes
The problem is the line beginning with the convert(decimal ... When it is included, I get the following error:
Error 8120: Column 'lyrReportSummaryData.unique_opens' is invalid in
the select list because it is not contained in either an aggregate
function or the GROUP BY clause.
I'm not sure how to resolve the error since I don't know how to use it in a GROUP BY clause (and it doesn't seem that I should need to do so).
Any suggestions for how to proceed? Thanks.
I'm sure someone with better DBA skills than me can point out a more efficient way of doing this, but...
If you perform the bulk of your query as an sub-query, you can then do the calculations on the result of your sub-query:
SELECT
MessageID_,
Issue,
mailed,
successes,
opens,
unique_opens,
convert(decimal(3,1),((convert(float,[unique_opens]))/[successes]) * 100) AS 'Rate'
FROM
(SELECT
outmail_.MessageID_,
CONVERT(VARCHAR(10),outmail_.Created_,120) AS 'Issue',
lyrReportSummaryData.mailed,
lyrReportSummaryData.successes,
COUNT(*) AS 'opens',
COUNT(DISTINCT clicktracking_.MemberID_) AS 'unique_opens'
FROM outmail_
RIGHT JOIN clicktracking_ ON clicktracking_.MessageID_ = outmail_.MessageID_
RIGHT JOIN lyrReportSummaryData ON lyrReportSummaryData.id = clicktracking_.MessageID_
GROUP BY outmail_.MessageID_, CONVERT(VARCHAR(10), outmail_.Created_,120), lyrReportSummaryData.mailed, lyrReportSummaryData.successes
) subquery /* was 'g' */
Effectively what this does is runs the grouping, and then based on that, does the calculation afterwards.
Subqueries must be given an alias (in this instance 'subquery') - even if you don't use that alias name.
I'm working with SQL Server 2005.
My query is:
SELECT (
SELECT COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
GROUP BY refKlinik_id
ORDER BY refKlinik_id
) as dorduncuay
And the error:
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP or FOR
XML is also specified.
How can I use ORDER BY in a sub query?
This is the error you get (emphasis mine):
The ORDER BY clause is invalid in
views, inline functions, derived
tables, subqueries, and common table
expressions, unless TOP or FOR XML is
also specified.
So, how can you avoid the error? By specifying TOP, would be one possibility, I guess.
SELECT (
SELECT TOP 100 PERCENT
COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
GROUP BY refKlinik_id
ORDER BY refKlinik_id
) as dorduncuay
If you're working with SQL Server 2012 or later, this is now easy to fix. Add an offset 0 rows:
SELECT (
SELECT
COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
GROUP BY refKlinik_id
ORDER BY refKlinik_id OFFSET 0 ROWS
) as dorduncuay
Besides the fact that order by doesn't seem to make sense in your query....
To use order by in a sub select you will need to use TOP 2147483647.
SELECT (
SELECT TOP 2147483647
COUNT(1) FROM Seanslar WHERE MONTH(tarihi) = 4
GROUP BY refKlinik_id
ORDER BY refKlinik_id
) as dorduncuay
My understanding is that "TOP 100 PERCENT" doesn't gurantee ordering anymore starting with SQL 2005:
In SQL Server 2005, the ORDER BY
clause in a view definition is used
only to determine the rows that are
returned by the TOP clause. The ORDER
BY clause does not guarantee ordered
results when the view is queried,
unless ORDER BY is also specified in
the query itself.
See SQL Server 2005 breaking changes
Hope this helps,
Patrick
If building a temp table, move the ORDER BY clause from inside the temp table code block to the outside.
Not allowed:
SELECT * FROM (
SELECT A FROM Y
ORDER BY Y.A
) X;
Allowed:
SELECT * FROM (
SELECT A FROM Y
) X
ORDER BY X.A;
You don't need order by in your sub query. Move it out into the main query, and include the column you want to order by in the subquery.
however, your query is just returning a count, so I don't see the point of the order by.
A subquery (nested view) as you have it returns a dataset that you can then order in your calling query. Ordering the subquery itself will make no (reliable) difference to the order of the results in your calling query.
As for your SQL itself:
a) I seen no reason for an order by as you are returning a single value.
b) I see no reason for the sub query anyway as you are only returning a single value.
I'm guessing there is a lot more information here that you might want to tell us in order to fix the problem you have.
Add the Top command to your sub query...
SELECT
(
SELECT TOP 100 PERCENT
COUNT(1)
FROM
Seanslar
WHERE
MONTH(tarihi) = 4
GROUP BY
refKlinik_id
ORDER BY
refKlinik_id
) as dorduncuay
:)
maybe this trick will help somebody
SELECT
[id],
[code],
[created_at]
FROM
( SELECT
[id],
[code],
[created_at],
(ROW_NUMBER() OVER (
ORDER BY
created_at DESC)) AS Row
FROM
[Code_tbl]
WHERE
[created_at] BETWEEN '2009-11-17 00:00:01' AND '2010-11-17 23:59:59'
) Rows
WHERE
Row BETWEEN 10 AND 20;
here inner subquery ordered by field created_at (could be any from your table)
In this example ordering adds no information - the COUNT of a set is the same whatever order it is in!
If you were selecting something that did depend on order, you would need to do one of the things the error message tells you - use TOP or FOR XML
Try moving the order by clause outside sub select and add the order by field in sub select
SELECT * FROM
(SELECT COUNT(1) ,refKlinik_id FROM Seanslar WHERE MONTH(tarihi) = 4 GROUP BY refKlinik_id)
as dorduncuay
ORDER BY refKlinik_id
For me this solution works fine as well:
SELECT tbl.a, tbl.b
FROM (SELECT TOP (select count(1) FROM yourtable) a,b FROM yourtable order by a) tbl
Good day
for some guys the order by in the sub-query is questionable.
the order by in sub-query is a must to use if you need to delete some records based on some sorting.
like
delete from someTable Where ID in (select top(1) from sometable where condition order by insertionstamp desc)
so that you can delete the last insertion form table.
there are three way to do this deletion actually.
however, the order by in the sub-query can be used in many cases.
for the deletion methods that uses order by in sub-query review below link
http://web.archive.org/web/20100212155407/http://blogs.msdn.com/sqlcat/archive/2009/05/21/fast-ordered-delete.aspx
i hope it helps. thanks you all
For a simple count like the OP is showing, the Order by isn't strictly needed. If they are using the result of the subquery, it may be. I am working on a similiar issue and got the same error in the following query:
-- I want the rows from the cost table with an updateddate equal to the max updateddate:
SELECT * FROM #Costs Cost
INNER JOIN
(
SELECT Entityname, costtype, MAX(updatedtime) MaxUpdatedTime
FROM #HoldCosts cost
GROUP BY Entityname, costtype
ORDER BY Entityname, costtype -- *** This causes an error***
) CostsMax
ON Costs.Entityname = CostsMax.entityname
AND Costs.Costtype = CostsMax.Costtype
AND Costs.UpdatedTime = CostsMax.MaxUpdatedtime
ORDER BY Costs.Entityname, Costs.costtype
-- *** To accomplish this, there are a few options:
-- Add an extraneous TOP clause, This seems like a bit of a hack:
SELECT * FROM #Costs Cost
INNER JOIN
(
SELECT TOP 99.999999 PERCENT Entityname, costtype, MAX(updatedtime) MaxUpdatedTime
FROM #HoldCosts cost
GROUP BY Entityname, costtype
ORDER BY Entityname, costtype
) CostsMax
ON Costs.Entityname = CostsMax.entityname
AND Costs.Costtype = CostsMax.Costtype
AND Costs.UpdatedTime = CostsMax.MaxUpdatedtime
ORDER BY Costs.Entityname, Costs.costtype
-- **** Create a temp table to order the maxCost
SELECT Entityname, costtype, MAX(updatedtime) MaxUpdatedTime
INTO #MaxCost
FROM #HoldCosts cost
GROUP BY Entityname, costtype
ORDER BY Entityname, costtype
SELECT * FROM #Costs Cost
INNER JOIN #MaxCost CostsMax
ON Costs.Entityname = CostsMax.entityname
AND Costs.Costtype = CostsMax.Costtype
AND Costs.UpdatedTime = CostsMax.MaxUpdatedtime
ORDER BY Costs.Entityname, costs.costtype
Other possible workarounds could be CTE's or table variables. But each situation requires you to determine what works best for you. I tend to look first towards a temp table. To me, it is clear and straightforward. YMMV.
On possible needs to order a subquery is when you have a UNION :
You generate a call book of all teachers and students.
SELECT name, phone FROM teachers
UNION
SELECT name, phone FROM students
You want to display it with all teachers first, followed by all students, both ordered by. So you cant apply a global order by.
One solution is to include a key to force a first order by, and then order the names :
SELECT name, phone, 1 AS orderkey FROM teachers
UNION
SELECT name, phone, 2 AS orderkey FROM students
ORDER BY orderkey, name
I think its way more clear than fake offsetting subquery result.
I Use This Code To Get Top Second Salary
I am Also Get Error Like
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
TOP 100 I Used To Avoid The Error
select * from (
select tbl.Coloumn1 ,CONVERT(varchar, ROW_NUMBER() OVER (ORDER BY (SELECT 1))) AS Rowno from (
select top 100 * from Table1
order by Coloumn1 desc) as tbl) as tbl where tbl.Rowno=2