SELECT
ffl2.fee_record_code,
(SELECT max(fee_record_code)
FROM fees_list ffl3
START WITH ffl3.fee_record_code = Nvl(ffl2.fes_associated_record, ffl2.fee_record_code)
CONNECT BY PRIOR ffl3.fee_record_code = ffl3.fes_associated_record) final_record_code
FROM
fees_list ffl2
SQL Server does not have CONNECT BY. You need to use a recursive CTE.
Unfortunately, you cannot put a recursive CTE into a subquery or derived table. So the easiest way to solve your particular problem is to use an inline Table Valued Function
CREATE OR ALTER FUNCTION dbo.GetMaxRecords (#fee_record_code int)
RETURNS TABLE
AS RETURN
WITH cte AS (
SELECT fee_record_code
FROM fees_list ffl3
WHERE ffl3.fee_record_code = #fee_record_code
UNION ALL
SELECT fee_record_code
FROM fees_list ffl3
JOIN cte ON cte.fee_record_code = ffl3.fes_associated_record
)
SELECT
fee_record_code = MAX(cte.fee_record_code)
FROM cte;
go
SELECT
ffl2.fee_record_code,
final_record_code = (
SELECT r.fee_record_code
FROM dbo.GetMaxRecords( ISNULL(ffl2.fes_associated_record, ffl2.fee_record_code) ) r
)
FROM
fees_list ffl2;
Related
The below code is getting error in SQL
Incorrect syntax near the keyword 'Select'.
This is my code for merge where InstalledSoftwareList is a used defined table.
MERGE [dbo].[TableName] AS TargetTable
USING UDTableName AS SourceTable
ON (TargetTable.[EId] = SourceTable.[EId]
AND TargetTable.[MId] = SourceTable.[MId]
AND TargetTable.PackageId = (SELECT Id FROM [PackagesDummyTable] SP WHERE SP.[Version] = SourceTable.[Version] AND SP.[Name] = SourceTable.[Name])
)
WHEN NOT MATCHED BY TARGET -- If the records in the Customer table is not matched?-- then INSERT the record
THEN INSERT ([Guid], [PackageId], [CName], [UUID], [MAC], [Date], [isUninstalled], [LastUpdatedDateTime], [DataCapturedTime], [SGuid], [UniqueId], [MId], [EId])
Select SourceTable.Guid,SP.PackageId,SourceTable.CName,SourceTable.UUID,SourceTable.MAC,SourceTable.Date,SourceTable.isUninstalled,GETUTCDATE(),SourceTable.DataCapturedTime,SourceTable.SGuid, SourceTable.UniqueId, SourceTable.MId, SourceTable.EId
FROM [PackagesDummyTable] SP WHERE SP.[Version] = SourceTable.[Version] AND SP.[Name] = SourceTable.[Name];
I was referring this https://msdn.microsoft.com/en-us/library/bb510625.aspx. And my syntax seems to be right.
Can anyone help me on this. I am using SQL Azure.
As #gotqn said, If you only need to prcess the new data, you can just you insert into statement.
If it's required that you must you MERG INTo, you can change your script to below
MERGE [dbo].[TableName] AS TargetTable
USING (
SELECT UN.[EId],UN.[MId],SP.ID ,UN.Guid,SP.PackageId,UN.CName,UN.UUID,UN.MAC,UN.Date,UN.isUninstalled
,UN.DataCapturedTime,UN.SGuid, UN.UniqueId
FROM UDTableName AS UN AS
INNER JOIN [PackagesDummyTable] SP ON SP.[Version] = UN.[Version] AND SP.[Name] = UN.[Name]
) SourceTable
ON TargetTable.[EId] = SourceTable.[EId]
AND TargetTable.[MId] = SourceTable.[MId]
AND TargetTable.PackageId = SourceTable.Id
WHEN NOT MATCHED BY TARGET -- If the records in the Customer table is not matched?-- then INSERT the record
THEN INSERT ([Guid], [PackageId], [CName], [UUID], [MAC], [Date], [isUninstalled], [LastUpdatedDateTime], [DataCapturedTime], [SGuid], [UniqueId], [MId], [EId])
VALUES( SourceTable.Guid,SourceTable.PackageId,SourceTable.CName,SourceTable.UUID,SourceTable.MAC,SourceTable.Date,SourceTable.isUninstalled,GETUTCDATE(),SourceTable.DataCapturedTime,SourceTable.SGuid, SourceTable.UniqueId, SourceTable.MId, SourceTable.EId)
;
MERGE is nice if you want to do more than one CRUD operations. In this case, we only need to insert new records. Could you try something like this:
INSERT INTO ([Guid], [PackageId], [CName], [UUID], [MAC], [Date], [isUninstalled], [LastUpdatedDateTime], [DataCapturedTime], [SGuid], [UniqueId], [MId], [EId])
SELECT SourceTable.Guid,SP.PackageId,SourceTable.CName,SourceTable.UUID,SourceTable.MAC,SourceTable.Date,SourceTable.isUninstalled,GETUTCDATE(),SourceTable.DataCapturedTime,SourceTable.SGuid, SourceTable.UniqueId, SourceTable.MId, SourceTable.EId
-- we need these two tables in order to import data
FROM UDTableName AS SourceTable
INNER JOIN [PackagesDummyTable] SP
ON SP.[Version] = SourceTable.[Version]
AND SP.[Name] = SourceTable.[Name]
-- we are joing this table in order to check if there is new data for import
LEFT JOIN [dbo].[TableName] AS TargetTable
ON TargetTable.[EId] = SourceTable.[EId]
AND TargetTable.[MId] = SourceTable.[MId]
-- we are importing only the data that is new
WHERE TargetTable.PackageId IS NULL;
I have a query like this:
DECLARE #year_start INT
DECLARE #year_end INT
SET #year_start = 2005
SET #year_end = 2014
; WITH p_year AS
(
SELECT p_year = #year_start
UNION ALL
SELECT p_year = p_year + 1
FROM p_year
WHERE p_year < #year_end
),
Interval AS
(---
),
CTE AS
(---
),
CTE_1 AS
(---
)
SELECT something
FROM CTE_1
WHERE Rank <= 3
ORDER BY something
I tried it using creating table valued function but can't get that how to manipulate with variables in the table valued function declaration.
Whereas I tried creating table valued function as:
CREATE FUNCTION P_Count()
RETURNS TABLE
AS
DECLARE ...
...
I want to make it a view but Declare statement not allows me. How can I make it a view?
your create function script misses a BEGIN:
CREATE FUNCTION P_Count()
RETURNS #tableName TABLE (structure here)
AS
BEGIN
DECLARE...
...
RETURN;
END;
here is the syntax reference on msdn
Maliks, I suppose, some were confused with your SQL. It was not immediately apparent that you use a recursive CTE to generate years in a range. There are lots of awesome ways to generate a sequence of integers (or numbers, in general) that can be combined with a CTE to emulate variables in a view. If numbers are generated way too often, consider building a separate (and indexed) table for them.
Here is what I think you were looking for. I omit the CTEs, rank and grouping you have not defined in your question. You can modify it as you wish:
WITH params AS (SELECT BegYr = 2005, EndYr=2014),
nums AS (SELECT DISTINCT n = number FROM master..spt_values WHERE number>=0)
SELECT Yr=BegYr + n FROM nums, params
WHERE n <= EndYr - BegYr
More generally, here is a sample view query that uses CTE to nicely emulate internal variable construction. You can test-run it in your version of SQL Server.
CREATE VIEW vwImportant_Users AS
WITH params AS (
SELECT
varType='%Admin%',
varMinStatus=1)
SELECT status, name
FROM sys.sysusers, params
WHERE status > varMinStatus OR name LIKE varType
SELECT * FROM vwImportant_Users
yielding output:
status name
12 dbo
0 db_accessadmin
0 db_securityadmin
0 db_ddladmin
also via JOIN
WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name
FROM sys.sysusers INNER JOIN params ON 1=1
WHERE status > varMinStatus OR name LIKE varType
also via CROSS APPLY
WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name
FROM sys.sysusers CROSS APPLY params
WHERE status > varMinStatus OR name LIKE varType
I created a user-defined function in SQL Server 2012 that returns XML. I would like to call the function in a SELECT statement. Is this possible?
When I try doing it, I get the error:
The FOR XML clause is not allowed in a ASSIGNMENT statement.
I want the SELECT statement to return a set of these named methods that have dependencies of other named methods within their logic.
In the main CTE, I get the latest versions of methods that have dependencies. The UDF goes thru the logic of each method and returns any methods called within it. So, I want to call the UDF in the SELECT statement and return XML of the dependent method names.
The function works and returns XML data. This is the function:
ALTER FUNCTION [dbo].[GetCalledMLMs]
(
-- Add the parameters for the function here
#MLM_Txt nvarchar(MAX)
)
RETURNS XML
AS
BEGIN
-- Declare the return variable here
DECLARE #CalledMLMs XML
Declare #MLMTbl table (pos int, endpos int, CalledMLM nvarchar(200))
--Logic to get the data...
Select #CalledMLMs = CalledMLM from #MLMTbl FOR XML PATH
-- Return the result of the function
RETURN #CalledMLMs
END
This is the CTE that calls the UDF.
;with cte as
(
select distinct Name, max(ID) as LatestVersion
from MLM_T
where Logic like '%:= MLM %' and Logic not like '%standard_libs := mlm%'
group by Name
)
select MLM2.Name, LatestVersion,
dbo.GetCalledMLMs(MLM2.Logic) as CalledMLMs
from cte join MLM_T MLM2 on cte.Name = MLM2.Name
and cte.LatestVersion = MLM2.ID
and MLM2.Active = 1 and MLM2.Status in (3, 4)
When running this query I get the error that XML is not allowed to be used in assignment statement.
Is there any way to call a function in the SELECT statment that returns an XML data type?
If you want to set a variable to a value you have to use SET and a scalar value on the right side.
The syntax SELECT #SomeVariable=SomeColumn FROM SomeTable is not possible with FOR XML (and rather dangerous anyway...), because the XML is not a column of the SELECT but something after the process of selecting.
Your problem is situated here:
Select #CalledMLMs = CalledMLM from #MLMTbl FOR XML PATH
Try to change this to
SET #CalledMLMs = (SELECT CalledMLM FROM #MLMTbl FRO XML PATH);
I solved the problem by changing the function to return a table, not XML.
So it looks like this:
FUNCTION [dbo].[GetCalledMLMsTbl]
(
-- Add the parameters for the function here
#MLM_Txt nvarchar(MAX)
)
--RETURNS XML
RETURNS #MLMTbl TABLE
(
pos int,
endpos int,
CalledMLM nvarchar(200)
)
AS
BEGIN
--logic here
insert into #MLMTbl (pos, endpos, CalledMLM) Values (#startpos, #endpos, #MLM_name)
RETURN
END
Then I called the function in the 'from' clause in the select
;with cte as
(
select distinct Name, max(ID) as LatestVersion
from CV3MLM
where Logic like '%:= MLM %' and Logic not like '%standard_libs := mlm%'
--and Name not like '%V61_CCC'
group by Name
)
select MLM2.Name, LatestVersion, C.CalledMLM
from cte join MLM_tbl MLM2 on cte.Name = MLM2.Name and cte.LatestVersion = MLM2.ID
and MLM2.Active = 1 and MLM2.Status in (3, 4)
cross apply dbo.GetCalledMLMsTbl(MLM2.Logic) C
order by MLM2.Name, LatestVersion
I need some help with a simple (simple in PostgreSQL, but I need in SQL Server 2008) update from select statement. I don't know how to pass "values" from rows as variables to the select statement in from clause. This is what i've done.
DECLARE #OldAnswerValue INT = 7;
DECLARE #Type INT =3;
SELECT A.Id as NewAnswer
FROM tblEvaluationAnswers A
WHERE A.AnswerValue=
CASE #OldAnswerValue
WHEN 0 THEN 1
WHEN 1 THEN 2
...
WHEN 9 THEN 5
END
AND AnswerType=#Type
and my update will look like
UPDATE transPersonEvaluation
SET UserAnswer=PEA.NewAnswer
FROM ( ) as PEA --here the select statement inside from
but I don't know how to pass #OldAnswerValue and #Type as parameters into the from clause. This values are extracted from each row of transPersonEvaluation wich I am updating.
In PostgreSQL I think it is like
UPDATE transPersonEvaluation PE
SET UserAnswer=PEA.NewAnswer
FROM (
SELECT A.Id as NewAnswer
FROM tblEvaluationAnswers A ... where A.AnswerType=PE.AnswerType) as PEA;
but it is throwing syntax error on sql server 2008.
Any help would be appreciated, Thanks!
in sql server your query would look like this.
UPDATE PE
SET PE.UserAnswer=PEA.NewAnswer
FROM transPersonEvaluation PE
JOIN
(
SELECT A.Id as NewAnswer
FROM tblEvaluationAnswers A ... ) as PEA ON PEA.AnswerType = PE.AnswerType;
I'm trying to select the max id from any n number linked tuples in a sql server db - we are writing an upgrade script for some data sets within an app, and need to know what the highest upgrade available is based on what the data's version is currently. For example, using the following simplified table 'versions':
oldVersionId newVersionId
1 2
2 3
3 4
10 11
We know we are version 1, and want to get the highest version out there that we can upgrade to; which would return 4 in this case, and not 11. We can have 0-n number of upgradable versions available at any given time. I'm not an sql wiz, and could only think to query using a variable number of chained selects:
select newVersion from versions where oldVersionId = (select newVersion from versions where oldVersionId = 1)
But it not an n numbered search, and won't return correctly if the number of elements is greater or less then the given. Is sql capable of performing such a query, and what elements / keywords should I be looking at to write one?
Solution:
You learn something new every day - I needed a hybrid of the two answers. Turns out sql can query a dataset using the tree-like child/parent linking that I'm way more comfortable with in OO languages.
In sql server you can set up a recursive tree walking call using a aliased table. You need an anchor and then the recursive bit. The first call is the anchor, I can use any value in the table, or a list of values, etc. The second select call just says to use the rest of the table to scan against.
Here is the syntax:
--Create the new alias (s)
;with s (oldVersionId, newVersionId) as
(
--set up the anchor node,
select oldVersionId, newVersionId from #t
where oldVersionId = 1
-- join it to the rest of the table, denoting that we only want nodes
-- where the old version is represented as a new version later
union all
select t.oldVersionId, t.newVersionId from #t as t
inner join s on t.oldVersionId = s.newVersionId
)
--Return the max value from the nodes I collected
select max(s.newVersionId) from s
Here is the solution with CTE - loop thru data while we have next match on oldVersionId = newVersionId:
declare #t table (
oldVersionId int,
newVersionId int )
insert into #t values (1,2)
insert into #t values (2,3)
insert into #t values (3,4)
insert into #t values (10,11)
insert into #t values (11,12)
insert into #t values (14,15)
declare #startVer int
set #startVer = 1
;with s (oldVersionId, newVersionId) as
(
select top 1 oldVersionId, newVersionId from #t
where oldVersionId = #startVer
union all
select t.oldVersionId, t.newVersionId from #t as t
inner join s on t.oldVersionId = s.newVersionId
)
select max(s.newVersionId)
from s
option (maxrecursion 0)
And here is solution without CTE - search for the last record which has newVersionId equals to 1 (1st version) plus the sum of imcremental updates to this version:
select max(t1.newVersionId)
from #t t1
where t1.oldVersionId >= #startVer
and t1.newVersionId = #startVer + (
select sum(newVersionId - oldVersionId)
from #t
where
oldVersionId >= #startVer and
oldVersionId < t1.newVersionId)
This problem can be solved by writing recursive queries to traverse recursive hierarchies in a table.
http://www.mssqltips.com/sqlservertip/1520/recursive-queries-using-common-table-expressions-cte-in-sql-server/
http://msdn.microsoft.com/en-us/library/ms186243.aspx
You effectively need to identify the final node in a linked list--seems to me your best bet would be to use the recursive features of CTEs to get to your 'max' version, but I'm not familiar enough with CTEs to get it working.
The following gets to the right answer, but only because I know how many links this particular dummy table will require beforehand; thus, not ideal.
CREATE TABLE #temp (
oldversionID SMALLINT,
newversionID SMALLINT )
INSERT INTO #temp
VALUES (1,2)
INSERT INTO #temp
VALUES (2,3)
INSERT INTO #temp
VALUES (3,4)
INSERT INTO #temp
VALUES (10,11);
select t1.oldversionID, t3.newversionID from #temp t1
inner join #temp t2
on t1.newversionId = t2.oldversionID
inner join #temp t3
on t2.newversionId = t3.oldversionID
Your problem is pretty much same as How to get the parent given a child in SQL SERVER 2005
I think same CTE will work for you.