I need help.
I write this query
SELECT SUM(fi.etiliquido) FROM fi WHERE fi.fno IN (
SELECT * from divideString(
SELECT TOP 1 REPLACE(CAST( u.nrdoc AS nvarchar),'/',',') FROM u_ups1 as u WHERE 1057 IN (
SELECT * FROM divideString(REPLACE(CAST(u.nrdoc AS nvarchar),'/',','))
)
)
)
but sql server return this error
Msg 156, Level 15, State 1, Line 4 Incorrect syntax near the keyword
'SELECT'. Msg 102, Level 15, State 1, Line 7 Incorrect syntax near
')'.
and I don't know why.
Can you help me?
UPDATE
divideString is a function get a string and returns the numbers in that string
CREATE FUNCTION divideString (#InStr VARCHAR(MAX))
RETURNS #TempTab TABLE
(id int not null)
AS
BEGIN
SET #InStr = REPLACE(#InStr + ',', ',,', ',')
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%,%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #TempTab(id) VALUES (#VALUE)
END
RETURN
END
You need parentheses around subqueries (except for in subqueries), so:
SELECT SUM(fi.etiliquido)
FROM fi
WHERE fi.fno IN (SELECT d.val
FROM divideString( (SELECT TOP 1 REPLACE(CAST( u.nrdoc AS nvarchar(max)), '/', ',')
FROM u_ups1 as u
WHERE 1057 IN (SELECT d.val
FROM divideString(REPLACE(CAST(u.nrdoc AS nvarchar(max)), '/', ',') d(val)
)
)
) d(val)
);
Also, using TOP with no ORDER BY is usually suspicious.
Storing multiple values in a single column is not recommended. However, I don't think you need a table-valued functions for this. LIKE should work:
SELECT SUM(fi.etiliquido)
FROM fi
WHERE EXISTS (SELECT 1
FROM (SELECT TOP 1 u.nrdoc
FROM u_ups1 u
WHERE '/' + u.nrdoc + '/' LIKE '%/1057/%'
) u
WHERE '/' + u.nrdoc + '/' LIKE '%/' + fi.fno + '/%'
);
And what you might want:
And, the logic that you want might be as simple as this:
SELECT SUM(fi.etiliquido)
FROM fi
WHERE EXISTS (SELECT 1
FROM u_ups1 u
WHERE '/' + u.nrdoc + '/' LIKE '%/1057/%' AND
'/' + u.nrdoc + '/' LIKE '%/' + fi.fno + '/%'
);
Related
Data
Approval_ID
-----------
1
2
3
4
5
6
7
8
9
10
Query
DECLARE
#id varchar(8000)
SELECT #id = COALESCE(#id + ', ', '') + '[' + Approval_ID + ']'
FROM (
SELECT DISTINCT Approval_ID
FROM Gate_III_CS_Approval
) Y
Result always
1,10,2,3,4,5,6,7,8,9
I've tried to add Order By
ORDER BY len(Approval_ID), Approval_ID
but have error
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified.
and I want to the result like this
1,2,3,4,5,6,7,8,9,10
Whats should I do?
Update :
;with cte as (
SELECT DISTINCT Approval_ID
FROM Gate_III_CS_Approval
)
SELECT #id = STUFF(
(SELECT concat(',', '[' + Approval_ID + ']')
FROM cte ORDER BY len(Approval_ID), Approval_id
FOR XML PATH('')
), 1, 1, '')
Using CTE and STUFF for XML PATH
-- replace CTE with your table, this is only an example
declare #id varchar(8000)
;with cte as (
select 1 n
union all
select n+1 n from
cte
where n < 10
)
select #id =
STUFF((
SELECT concat(',', n)
FROM cte
order by n
FOR XML PATH('')
), 1, 1, '')
select #id
programmatically cast n from alphanumeric to int for sorting
It seems you are using a varchar field instead of an integer for Approval_ID.
For ordering it based on the varchar field, you can try the method from maSTAShuFu's answer.
Here I am updating it with your query from question.
SELECT STUFF(
(SELECT CONCAT(',[', Approval_ID,']')
FROM <your_table>
ORDER BY cast(Approval_ID as int)
FOR XML PATH('')), 1, 1, '')
Maybe you can try to convert varchar to int for this purpose. I built an example here
DECLARE
#id varchar(8000)
SELECT #id = COALESCE(#id + ', ', '') + '[' + CAST(ID AS VARCHAR(10)) + ']'
FROM (
SELECT DISTINCT CAST(id AS INT) ID
FROM TABLA
) Y
SELECT #ID
I am writing a query that roughly has this structure:
SELECT Name, <calculated-valued> as Version FROM <tables>
This calculated value needs to work like so: I have a varchar column 'Name' that could contain something like 'ABC' and I want to convert each letter into ASCII, and append them back together to form '65.66.67' in this example. (An empty string should return '0') Is there any way to do this?
My approach wasn't very good, but up to 5 characters I could do the following:
SELECT
CASE WHEN LEN(Name) = 0 THEN '0'
ELSE CAST(ASCII(SUBSTRING(Name, 1, 1)) as varchar(max)) +
CASE WHEN LEN(Name) = 1 THEN ''
ELSE '.' + CAST(ASCII(SUBSTRING(Name, 2, 1)) as varchar(max)) +
CASE WHEN LEN(Name) = 2 THEN ''
ELSE '.' + CAST(ASCII(SUBSTRING(Name, 3, 1)) as varchar(max)) +
CASE WHEN LEN(Name) = 3 THEN ''
ELSE '.' + CAST(ASCII(SUBSTRING(Name, 4, 1)) as varchar(max)) +
CASE WHEN LEN(Name) = 4 THEN ''
ELSE '.' + CAST(ASCII(SUBSTRING(Name, 5, 1)) as varchar(max))
END
END
END
END
END AS MyColumn
FROM <tables>
Is there a better way to do this? Ideally a method that can take any length of string?
Either that or can I cast letters into a hierarchyid datatype? I need to create things like 1/2/a/bc/4// or whatever, but hierarchyid doesn't support that. So instead I'm trying to convert it to 1/2/97/98.99/4/0 so I can convert and maintain the correct order. This column is only used for sorting.
Thanks for any help!
One method is a recursive CTE:
with cte as (
select Name, 1 as lev
cast(ascii(substring(name, 1, 1)) as varchar(max)) as ascii_name
from t
union all
select Name, lev + 1,
ascii_name + '.' + cast(ascii(substring(name, lev + 1, 1)) as varchar(max))
from cte
where len(Name) > lev
)
select Name, ascii_name
from cte;
Another option is with an ad-hoc tally table and a CROSS APPLY
Declare #YourTable table (Name varchar(25))
Insert Into #YourTable values
('ABC'),
('Jack'),
('Jill'),
('')
Select A.Name
,Version = isnull(B.String,'0')
From #YourTable A
Cross Apply (
Select String=Stuff((Select '.' +cast(S as varchar(5))
From (Select Top (len(A.Name))
S=ASCII(substring(A.Name,Row_Number() Over (Order By (Select NULL)),1))
From master..spt_values ) S
For XML Path ('')),1,1,'')
) B
Returns
Name String
ABC 65.66.67
Jack 74.97.99.107
Jill 74.105.108.108
0
When I use below 2 queries separately I get output successfully
Query #1
DECLARE #ID VARCHAR(1000)
SET #ID = ''
SELECT #ID = #ID + CAST(int_ID AS VARCHAR(1000))
FROM MATRIX_RELATIONSHIP
SELECT COUNT(int_ID) [Count], YEAR(dt_5841_OF) [date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME = 4
AND CHARINDEX(CONVERT(VARCHAR, int_ID), ('''' + Replace((#ID),',',''',''') + '''')) > 0
GROUP BY YEAR(dt_5841_OF);
Output:
Count | year
02 2016
Query #2
SELECT
COUNT(*) [Count1], YEAR(dt_modifiedOn) [date]
FROM
MATRIX_RELATIONSHIP
GROUP BY
YEAR(dt_modifiedOn);
Output:
Count | year
02 2016
But when I use both queries to form a full outer join something like below:
SELECT
tab1.Count, tab2.Count1, tab1.date
FROM
(DECLARE #ID VARCHAR(1000)
SET #ID = ''
SELECT #ID = #ID+CAST(int_ID AS VARCHAR(1000))
FROM MATRIX_RELATIONSHIP
SELECT COUNT(int_ID) [Count], YEAR(dt_5841_OF) [date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME = 4
AND CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) > 0
GROUP BY YEAR(dt_5841_OF)) tab1
FULL OUTER JOIN
(SELECT COUNT(*) [Count1], YEAR(dt_modifiedOn) [date]
FROM MATRIX_RELATIONSHIP
GROUP BY YEAR(dt_modifiedOn)) tab2 ON tab1.date = tab2.date;
I get these errors:
Msg 156, Level 15, State 1, Line 2
Incorrect syntax near the keyword 'DECLARE'.
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near 'tab2'.
Expected result
Count | Count1 | year
02 02 2016
EDIT
I have tried placing declare and set outside the query too but still there the issue persists
DECLARE #ID VARCHAR(1000) SET #ID=''
SELECT tab1.Count,tab2.Count1,tab1.date from
( SELECT #ID= #ID+CAST(int_ID AS VARCHAR(1000))
from MATRIX_RELATIONSHIP SELECT COUNT(int_ID)[Count],YEAR(dt_5841_OF)[date] FROM TRANS_IDENTIFICATIONS WHERE smallint_209_ME=4 and CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) >
0 GROUP BY YEAR(dt_5841_OF)) tab1
FULL OUTER JOIN
(SELECT COUNT(*)[Count1],YEAR(dt_modifiedOn)[date]
FROM MATRIX_RELATIONSHIP GROUP BY YEAR(dt_modifiedOn)) tab2
ON tab1.date=tab2.date;
Which leads to another set of errors:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '='.
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'tab2'.
DECLARE #ID VARCHAR(1000)
SET #ID='';
SELECT #ID = #ID + CAST(int_ID AS VARCHAR(1000)) from MATRIX_RELATIONSHIP;
SELECT MAX(Count) AS Count, MAX(Count1) AS Count1, date
FROM
(
SELECT COUNT(int_ID)[Count], null AS [Count1], YEAR(dt_5841_OF)[date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME = 4
and CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) >
0 GROUP BY YEAR(dt_5841_OF)
UNION ALL
SELECT NULL AS [Count], COUNT(*)[Count1],YEAR(dt_modifiedOn)[date]
FROM MATRIX_RELATIONSHIP
GROUP BY YEAR(dt_modifiedOn)
)AS temp
GROUP BY [date]
this is not a valid from
it is two select statements
from
( DECLARE #ID VARCHAR(1000)
SET #ID='' SELECT #ID= #ID+CAST(int_ID AS VARCHAR(1000))
from MATRIX_RELATIONSHIP
SELECT COUNT(int_ID)[Count],YEAR(dt_5841_OF)[date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME=4
and CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) > 0
GROUP BY YEAR(dt_5841_OF)
)
Your DECLARE and SET has to be outside of the SELECT. But what is its purpose?
remove the DECLARE #ID VARCHAR(1000);
SET #ID='' from the select statement.
Also declare the variable at the top of your statement
and rather writing two separate select statement use inner join on int_id and then do the outer join it will work
DECLARE #ID VARCHAR(1000)
SET #ID = ''
select * from
(
SELECT #ID+ CAST(MATRIX_RELATIONSHIP.int_ID AS varchar(1000)) AS count1, COUNT(TRANS_IDENTIFICATIONS.int_ID) AS count2, YEAR(TRANS_IDENTIFICATIONS.dt_5841_OF) AS date1
FROM MATRIX_RELATIONSHIP INNER JOIN
TRANS_IDENTIFICATIONS ON MATRIX_RELATIONSHIP.int_ID = TRANS_IDENTIFICATIONS.int_ID
WHERE (TRANS_IDENTIFICATIONS.smallint_209_ME = 4) AND (CHARINDEX(CONVERT(varchar, TRANS_IDENTIFICATIONS.int_ID), '''' + REPLACE(#ID, ',', ''',''') + '''') > 0)
GROUP BY YEAR(TRANS_IDENTIFICATIONS.dt_5841_OF),MATRIX_RELATIONSHIP.int_ID
union
(
SELECT '' as count1, COUNT(*) [Count2], YEAR(dt_modifiedOn) [date1]
FROM MATRIX_RELATIONSHIP
GROUP BY YEAR(dt_modifiedOn)
)
) as tbl
I hope this works for you... Do let me know
I have the following select statement that returns exactly what I want:
DECLARE #result varchar(max) = ''
SELECT #result += (result.Fullname + '<br/>')
FROM (SELECT DISTINCT Fullname
FROM Providers
WHERE Status='A') as result
select substring(#result, 0, len(#result) - 4)
The only problem is, I want the output from this query to be displayed as a column entry from a larger select statement.
Eg.
SELECT
Column AS [AColumnName],
SELECT #result += (result.Fullname + '<br/>')
FROM (SELECT DISTINCT Fullname
FROM Providers
WHERE Status='A') as result
select substring(#result, 0, len(#result) - 4) as [LenderList]
FROM
Table
But I am currently getting the error: Incorrect syntax near the keyword 'SELECT'.
The error pointing to line 4
Any ideas?
You need aggregate string concatenation in SQL Server. There are already many answers on the subquery, but to save you the trouble:
SELECT Column AS [AColumnName],
STUFF((SELECT DISTINCT '<br/>' + Fullname
FROM Providers
WHERE Status = 'A'
FOR XML PATH (''), TYPE
).value('.', 'varchar(max)'
), 1, 5, ''
) as result
FROM Table;
The use of the type is important because your string has special XML characters.
Can you simply run it in 2 statements?
SELECT #result += (result.Fullname + '<br/>')
FROM (SELECT DISTINCT Fullname
FROM Providers
WHERE Status='A') as result
SELECT
Column AS [AColumnName],
substring(#result, 0, len(#result) - 4)
FROM Table
Which Database? If you can use for xml, then something like...
select substring(a.innards, 0, len(a.innards) - 4) as [LenderList]
from
(
SELECT innards = STUFF(
(SELECT DISTINCT Fullname + '</br>'
FROM Providers
WHERE [Status] = 'A'
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)')
, 1
, 0
, '')
) a
I'm storing some queries in a table column so I can execute them later passing some parameters.
But it has been really annoying to format the query into an Update sentence, because of the special characters.
For Example:
SELECT * FROM MOUNTAINS WHERE MON_NAME='PALMA' AND MON_DESC LIKE '%TRANVULCANIA%'
Then I need the string just for the udpate query:
UPDATE QUERIES
SET QUE_SEL='SELECT * FROM MOUNTAINS WHERE MON_NAME='''+'PALMA'+''' AND MON_DESC LIKE '''+'%TRANVULCANIA%'+''' '
WHERE QUE_ID=1
as you can see the first ' must be replaced for '''+' but the next door ' must be replaced by '+'''
This is the query I'm working on:
DECLARE #QUERY VARCHAR(MAX)
SELECT #QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''' '
SELECT
t.r.value('.', 'varchar(255)') AS token
, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS id
FROM (
SELECT myxml = CAST('<t>' + REPLACE(#QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
) p
CROSS APPLY myxml.nodes('/t') t(r)
this is the result:
token id
-------------------------------------------------- --------------------
SELECT * FROM QUERIES WHERE QUE_NOMBRE= 1
' 2
PRUEBA 1 3
' 4
5
Now I want a column that tell me when to open and when to close and then I can set the final replace.
Adapting the solution given by #rivarolle
DECLARE #QUERY VARCHAR(MAX)
DECLARE #FORMATTED varchar(max)
SELECT #QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''''
;WITH TOKENS AS(
SELECT
t.r.value('.', 'varchar(MAX)') AS token
, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Id
FROM (
SELECT myxml = CAST('<t>' + REPLACE(#QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
) p
CROSS APPLY myxml.nodes('/t') t(r)
)
,
Tokens2 as (
SELECT
TOKENS.token as token
,quotes.row%2 as tipoapostrofe
from Tokens
left join (select row_number() over( order by Id asc) as row, a.* FROM (SELECT * from Tokens) a where Token = '''') quotes
on quotes.Id = Tokens.Id
)
SELECT #FORMATTED = STUFF((
SELECT ' ' + REPLACE(token,'''',CASE tipoapostrofe WHEN 1 THEN '''''''+''' WHEN 0 THEN '''+''''''' ELSE '' END) AS [text()]
FROM Tokens2
FOR XML PATH('')
), 1, 1, '')
print #FORMATTED
This Works, just need a function for cleaning XML special characters and another for putting back, and the Dynamic queries are printed ready for an update.
I think its not necessary to replace an apostrophe with '''+' to open and '+''' to close, I made some probes and you can exec a query that you replace opening and closing apostrophes with the same.. for example '''+' for open and '''+' for close.
So the query would be:
DECLARE #QUERY VARCHAR(MAX)
DECLARE #FORMATTED varchar(max)
SELECT #QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''''
SELECT #FORMATTED= STUFF((
SELECT ' ' +
(SELECT
CASE
WHEN t.r.value('.', 'varchar(250)')='''' THEN REPLACE(t.r.value('.', 'varchar(250)'), '''','''''''+''')
ELSE t.r.value('.', 'varchar(250)')
END
) AS [text()]
-- , ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS id
FROM (
SELECT myxml = CAST('<t>' + REPLACE(#QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
) p
CROSS APPLY myxml.nodes('/t') t(r)
FOR XML PATH('')
), 1, 1, '')
SET #FORMATTED=REPLACE(#FORMATTED,' ','')
PRINT #FORMATTED
then I get:
SELECT * FROM QUERIES WHERE QUE_NOMBRE= '''+' PRUEBA 1 '''+'
then I copy into a variable and execute
DECLARE #VAR VARCHAR(500)
SET #VAR='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'''+' '
EXEC(#VAR)
It Works for very simple queries, but with longer and complicated queries it doesn't works..
Assuming your token table is Tokens(Token, Id, Position):
update Tokens
set position = quotes.row%2
from Tokens
left join (select row_number() over( order by Id asc) as row, a.* FROM (SELECT * from Tokens) a where Token = '''') quotes
on quotes.Id = Tokens.Id
The position column will have a value of 1 for starting quote and 0 for closing quote. NULL for the rest.