Use of table valued function in order by clause - sql-server

Can I use my table valued function in order by clause of my select query????
Like this :
declare #ID int
set #ID=9011
Exec ('select top 10 * from cs_posts order by ' + (select * from dbo.gettopposter(#ID)) desc)
GetTopPoster(ID) is my table valued function.
Please help me on this.

You can use a table-valued function with a join. That also allows you to choose any combination of columns to sort by:
select top 10 *
from cs_posts p
join dbo.gettopposter(#ID) as gtp
on p.poster_id = gtp.poster_id
order by
gtp.col1
, gtp.col2

Yes. You can use a Table Valued Function just as a normal table.
Your query is not valid SQL though, despite the TVF.
For further reference:
http://msdn.microsoft.com/en-us/library/ms191165.aspx

You can't do it like that - how does it know what to order by? It doesn't know how the TVF relates to the original query. You can join the two however (as I assume cs_posts has an id column which relates to the TVF) and then order by the the TVF id column.

Related

Table Valued Function with Recursive CTE

Just for fun, I’m trying to write a table valued function to generate a table of dates. For testing purposes, I am hard-coding values which should be passed in variables.
By itself, this works:
WITH cte AS (
SELECT cast('2021-10-01' AS date) AS date
UNION ALL
SELECT dateadd(day,1,date) FROM cte WHERE date<current_timestamp
)
SELECT * FROM cte OPTION(maxrecursion 0);
Note the OPTION at the end.
As a function, it won’t work unless I remove the OPTION clause at the end:
CREATE FUNCTION dates(#start date, #rows INT) RETURNS TABLE AS
RETURN
WITH cte AS (
SELECT cast('2021-10-01' AS date) AS date
UNION ALL
SELECT dateadd(day,1,date) FROM cte WHERE date<current_timestamp
)
SELECT * FROM cte -- OPTION(maxrecursion 0)
;
For the test data, that’s OK, but it will certainly fail if I give it date at the beginning of the year, since it involves more than 100 recursions.
Is there a correct syntax for this, or is it another Microsoft Quirk which needs a workaround?
I think this may be the answer.
In an answer to another question, #GarethD states:
If you think of a view more as a stored subquery than a stored query … and remember that its definition is expanded out into the main query …
(Incorrect Syntax Near Keyword 'OPTION' in CTE Statement).
If that’s the case, a view can’t include anything that can’t be included in a subquery. That includes the ORDER BY clause and hints such as OPTION.
I have yet to make sure, but I can guess that the same goes for a Table Valued Function. If so, the answer is no, there is no way include the OPTION clause.
Note that other DBMSs are more accommodating in what can be included in subqueries, so I don’t imagine that they have the same limitations.
The solution is to use a multi-statement Table Valued Function:
DROP FUNCTION IF EXISTS dates;
GO
CREATE FUNCTION dates(#start date, #end date) RETURNS #dates TABLE(date date) AS
BEGIN
WITH cte AS (
SELECT #start AS date
UNION ALL
SELECT dateadd(day,1,date) FROM cte WHERE date<#end
)
INSERT INTO #dates(date)
SELECT date FROM cte OPTION(MAXRECURSION 0)
RETURN;
END;
GO
SELECT * FROM dates('2020-01-01','2021-01-01');
Inline Table Valued Functions are literally inlined, and clauses such as OPTION can only appear at the very end of an SQL statement, which is not necessarily at the end of the inline function.
On the other hand, a Multi Statement Table Valued function is truly self-contained, so the OPTION clause is OK there.

Is this a SQL Server table-valued function?

Can anyone explain this T-SQL statement:
select *
from (select getdate()) as func(param)
You can copy & paste the code, and then run it
There is no table valued function or dynamic SQL at all. It is simple subquery:
inner query: select getdate()
outer query: SELECT * FROM (inner_query) AS func(param)
func - it is just alias for subquery
param - it is alias for column
It could be rewritten as:
select sub.current_date_value
from (select getdate() AS current_date_value) as sub
The inner select query is a derived table. Search for that term to lean more. This is functionally identical (no pun intended) to:
SELECT GETDATE() AS param;
There is no need to use a derived table here.

SQL Server user defined function returns table -- cannot call it from select query

I cannot get this type of select query (pseudo-code) to work. The UDF returns a table with 8 columns in a single row for a given 'UID_VEHICLE'. It works perfectly when the 'UID_VEHICLE' is provided as a constant like 3308. But I need one row of these function-results for each vehicle for a given customer -- up to 100 rows to be returned.
SELECT
*
FROM
[dbo].[fnGetNextDOT_InspectionData](UID_VEHICLE)
WHERE
UID_VEHICLE IN (SELECT UID_VEHICLE
FROM tVEHICLES
WHERE UID_CUSTOMER = 88);
Your comments and solutions are welcome...thanks...John
When passing row values from a query into a TVF, you need to use CROSS APPLY or OUTER APPLY (starting with SQL Server 2005):
SELECT * -- or dot.*, or whatever is desired
FROM tVEHICLES veh
CROSS APPLY [dbo].[fnGetNextDOT_InspectionData](veh.UID_VEHICLE) dot
WHERE veh.UID_CUSTOMER = 88;

SQL Server how to pass table column like ID to scalar function in same database

I need to pass all id values to the function. How can I do this?
Like if I can loop on all id and pass all id for these fun which scalar function
empFn(emp.[id])
You can use table valued parameters to do this:
http://msdn.microsoft.com/en-us/library/bb510489.aspx
There are many many examples on the net.
If I get your question right, you should use CROSS APPLY
SELECT *
FROM dbo.employees emp
CROSS APPLY (SELECT * FROM dbo.empFn(emp.[id]))

Can select into add a new field to the resulting table?

I've got a SQL statement in SQL Server 2005 that looks something like this:
SELECT * INTO #TempTable FROM FirstTable WHERE <complex where clause>
What I would really, really like is to have the resulting temp table have an extra field that is essentially an integer field counting from 1 up in the order the where clause returned the records.
Is this possible?
(Essentially, I want to be able to return a subset of the records returned from the first select statement, along the lines of "lines 45 through 179".)
Try this, using Row_Number:
-- insert into temp table
SELECT *,
ROW_NUMBER() OVER (ORDER BY SortColumn) AS SortColumn INTO #TempTable
FROM FirstTable
WHERE <complex where clause>
-- check the results and drop the table
SELECT * FROM #TempTable WHERE SortColumn BETWEEN 45 AND 179 ORDER BY SortColumn
DROP TABLE #TempTable
Obviously you'll need to replace SortColumn with whatever makes sense in your case
Edit:
If you're just trying to do paging, there are lots of examples of that:
http://www.davidhayden.com/blog/dave/archive/2005/12/30/2652.aspx
http://www.sqlteam.com/article/server-side-paging-using-sql-server-2005
http://www.google.com/search?q=sql+server+2005+paging

Resources