I want to split a string in a column that is separated by space into multiple column is SQL.
I used the query below, but I get NULL values
select
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 1) AS Country_Code,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 2) AS iso_Code,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 3) AS status,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 5) AS date,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 6) AS rate,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 7) AS fx
FROM process.FX_RAW_DATA_OUT;
GO
You don't state what version of SQL Server you are running. If STRING_SPLIT is not available on your version, you can do as follows (I think you are trying to split column FX_RAW_DATA on table process). Basically, you apply the calculation of each space one after the other, then substring each:
SELECT
Country_Code = SUBSTRING(p.FX_RAW_DATA, 1, v1.chr - 1),
iso_Code = SUBSTRING(p.FX_RAW_DATA, v1.chr + 1, v2.chr - v1.chr - 1),
status = SUBSTRING(p.FX_RAW_DATA, v2.chr + 1, v3.chr - v2.chr - 1),
date = SUBSTRING(p.FX_RAW_DATA, v3.chr + 1, v4.chr - v3.chr - 1),
rate = SUBSTRING(p.FX_RAW_DATA, v4.chr + 1, v5.chr - v4.chr - 1),
fx = SUBSTRING(p.FX_RAW_DATA, v5.chr + 1, LEN(p.FX_RAW_DATA))
FROM process p
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA)) v1(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v1.chr + 1)) v2(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v2.chr + 1)) v3(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v3.chr + 1)) v4(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v4.chr + 1)) v5(chr);
The first substring always starts at 1 and ends at the first break, the last substring you can just pass the full length to get the remainder of the string.
It's not very clear from your example sample data and expected results what your data looks like. I have made some assumptions and example below should be easy to change to match your data as required.
DECLARE #stringarray varchar(max), --String holding your data
#Splitcharc char(1), --split character, space in your example
#X xml
set #stringarray = '01AED AUD M 30122020 .3541000 11' --example data line
set #Splitcharc = '' -- this can be changed if needed
-- We start off by formatting your string into an XML format
set #X = CONVERT(xml,' <Table> <Row> <col>' +
REPLACE(#stringarray,#Splitcharc,'</col> <col>') + '</col></Row> </Table> ')
-- The below show how you "query" each of the "columns" returned
SELECT
Tbl.cl.value('col[1]','VARCHAR(20)') country_code,
Tbl.cl.value('col[2]','VARCHAR(20)') ISO_code,
Tbl.cl.value('col[3]','VARCHAR(20)') [status],
Tbl.cl.value('col[4]','VARCHAR(20)') [date],
Tbl.cl.value('col[5]','VARCHAR(20)') rate,
Tbl.cl.value('col[6]','VARCHAR(20)') fx
FROM #X.nodes('/Table/Row') as Tbl(cl)
Related
I know that Replace < and > with < and > in sql server has been asked at
Replace “<” and “>” with “<” and “>” in sql server
but I need to expand upon it. I am trying to create formatted HTML code from a MS 2016 SQL server.
What I have is:
DECLARE #json nvarchar(max) = (SELECT DISTINCT AU2.PMID,
SUBSTRING(
(
SELECT ', '+ CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</' + AU1.Format + '>' ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM dbo.[Publication.PubMed.Author] AU1
WHERE AU1.PMID = AU2.PMID
ORDER BY AU1.PmPubsAuthorID
FOR XML PATH ('')
), 3, 1000) + '. Journal Name ' [Authors]
FROM dbo.[Publication.PubMed.Author] AU2
WHERE AU2.[PMID] =27702896 FOR JSON AUTO)
SELECT #json
And what I get back is:
Name DG, Name K, Name A, Chen FK, Song X, Pirun M, Santiago PM, Kim-Kiselak C, Platt JT, Lee E, Hodges E, <b>Rosebrock AP</b>, Bronson RT, Socci ND, Hannon GJ, Jacks T, Varmus H Journal Name
If I try to put TYPE into the
FOR XML PATH(''), TYPE
I get an error saying:
Argument data type xml is invalid for argument 1 of substring function.
I've tried to add REPLACE
replace(CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</b>' ELSE
AU1.LastName + ' ' + AU1.Initials END, '<', '<')
But then I get an error
The xml data type cannot be selected as DISTINCT because it is not comparable.
The best that I can come up with is:
SET #json = replace(#json, '<\', '<')
SET #json = replace(#json, '<', '<')
SET #json = replace(#json, '>', '>')
Just before the final SELECT #json.
I will have over a 1000 records that I need to pull. Do I need to do this is steps?
Based upon TT code I changed mine to
DECLARE #json nvarchar(max) = (SELECT DISTINCT AU2.PMID,
SUBSTRING(
(
SELECT ', '+ CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</b>' ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM dbo.[Publication.PubMed.Author] AU1
WHERE AU1.PMID = AU2.PMID
ORDER BY AU1.PmPubsAuthorID
FOR XML PATH (''),TYPE).value('.[1]','NVARCHAR(MAX)'
), 1, 1000) + '. Journal Name ' [Authors]
FROM dbo.[Publication.PubMed.Author] AU2
WHERE AU2.[PMID] =27702896 FOR JSON AUTO)
And that woks fine. but see comment below
As far as I can tell you are on the right track with FOR XML PATH(''), TYPE. It's just that you then have an XML text value which you need to convert to a string (i.e. of type [N]VARCHAR(X)). This can be done with the XML value() method.
An example (fiddle):
CREATE TABLE t(s NVARCHAR(16));
INSERT INTO t(s)VALUES(N'1'),(N'2'),(N'3'),(N'4'),(N'5'),(N'6');
SELECT
(
SELECT N'<b>'+s+N'</b>'
FROM t
FOR XML PATH(''),TYPE
).value('.[1]','NVARCHAR(MAX)');
results in
<b>1</b><b>2</b><b>3</b><b>4</b><b>5</b><b>6</b>
I need to generate XML in the following format :
I haven't gone too far with the xml part of the task as I encountered following situation, you can tell that this obviously was not my intention.
How can I handle this properly considering that BBAN and IBAN need to be inside AccountNoas well as that I want it formatted according to the first picture.
The complete query along with my fair attempt of generating xml looks like this:
DECLARE #AccountType NVARCHAR(3);
DECLARE #kodBanke NVARCHAR(3);
SET #AccountType = 'T';
SET #kodBanke = ( SELECT vrednost FROM dbini WHERE IDENT = 'KOD' AND SECTION = 'PP' );
WITH Ent_Posta
AS
(
SELECT e.naziv,p.posta,e.sifra
FROM entitet AS e
INNER JOIN poste AS p ON e.sifra = p.entitet
)
SELECT (
SELECT
[dbo].[brojracuna](#kodBanke,i.partija) AS 'BBAN',
[dbo].[GENERATEIBAN](i.partija) AS 'IBAN'
FOR XML PATH('AccountNo'), ELEMENTS, ROOT('Account')
),
#accountType AS 'AccountType',
(a.ime + ' ( ' + a.roditel + ' ) ' + a.prezime) AS 'Name',
a.embg AS 'UID',
CASE status
WHEN 2 THEN 'A'
WHEN 4 THEN 'B'
WHEN 8 THEN 'U'
END AS 'Status',
c.sifra AS 'Territory',
#kodBanke as 'ID_Bank',
REPLACE(CONVERT(VARCHAR(10), i.DOTVaRANJE, 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(s, i.DOTVaRANJE)),2) AS OpeningDate,
REPLACE(CONVERT(VARCHAR(10),'2006.09.28 ', 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, '2006.09.28' )), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, '2006.09.28 ')), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2),DATEPART(s,'2006.09.28 ')),2) AS ClosingDate
FROM adresar AS a
INNER JOIN istdden AS i
ON a.embg = i.embg
INNER JOIN Ent_Posta as c
ON a.postbroj = c.posta
FOR XML PATH ('Account'), ROOT('Accounts');
Upon removal of this part I get...
<Accounts>
<Account>
<BBAN>5710543102313248</BBAN>
<IBAN>BA39531231634039248</IBAN>
<AccountType>T</AccountType>
<Name>DARKO ( DRAGAN ) TESIC</Name>
<UID>0000005467234</UID>
<Status>A</Status>
<Territory>1</Territory>
<ID_Bank>571</ID_Bank>
<OpeningDate>20081205-000000</OpeningDate>
<ClosingDate>20060928-000000</ClosingDate>
</Account>
... but now AccountNO is missing.
Your question is not all clear, but - if I get this correctly - you are fighting with 1:1 values, but within some deeper nesting.
You can use an XPath-like expression within [] in connection with FOR XML PATH. Check this out:
SELECT 'blah' AS FirstNode
,'blub' AS [SecondNode/OneDeeper]
,'blib' AS [SecondNode/OneMore]
,'ballaballa' AS [ThirdNode]
FOR XML PATH('row'),ROOT('root');
the resutl (look especially at <SecondNode>:
<root>
<row>
<FirstNode>blah</FirstNode>
<SecondNode>
<OneDeeper>blub</OneDeeper>
<OneMore>blib</OneMore>
</SecondNode>
<ThirdNode>ballaballa</ThirdNode>
</row>
</root>
If this is not what you need, please tag with the actual RDBMS (product and version) and please read How to ask a good SQL question and How to create a MCVE
For your issue it might be enough to use AS [AccountNo/IBAN] in your query.
I have a temp table called #temp, and I need to get all the CDate column from that table, to build a string.
The CDate list in that table is (20171209, 20171210....20171223)
I expected to see
'A.[20171209] as [20171209], A.[20171210] as [20171210],
A.[20171211] as [20171211], A.[20171212] as [20171212],
A.[20171213] as [20171213], A.[20171214] as [20171214],
A.[20171215] as [20171215], A.[20171216] as [20171216],
A.[20171217] as [20171217], A.[20171218] as [20171218],
A.[20171219] as [20171219], A.[20171220] as [20171220],
A.[20171221] as [20171221], A.[20171222] as [20171222],
A.[20171223] as [20171223], '
however the result I got is missing the first date , ie 'A.[20171209] as [20171209]'
Here is my code:
SELECT
#col2 = ISNULL(#col2 + 'A.' + QUOTENAME(CDate) + ' as ' + QUOTENAME(CDate) + ', ' , '')
FROM
(SELECT DISTINCT CDate FROM #temp) AS tmp;
Your current approach will not work in some cases, it is an undocumented feature, always use For Xml path to concatenating the rows into csv.
SET #col2 = stuff((SELECT ', A.' + Quotename(CDate) + ' as '
+ Quotename(CDate)
FROM (SELECT DISTINCT CDate
FROM #temp) a
FOR xml path('')),1,1,'')
I have the following query and want to order the list by User name
select distinct
SUBSTRING(u.FullName, CHARINDEX(' ', u.FullName) + 1, LEN(u.FullName)) + ', ' + SUBSTRING(u.FullName, 1, CHARINDEX(' ', u.FullName) - 1) as UserName
from
Users u
where
u.Active = 1
order by
SUBSTRING(u.FullName, CHARINDEX(' ', u.FullName) + 1, LEN(u.FullName)) + ', ' + SUBSTRING(u.FullName, 1, CHARINDEX(' ', u.FullName) - 1)
The problem here is two of the users with last name r and w always show at top of the list, while the rest of the list is sorted A to Z.
Any suggestion how this can be fixed?
I got it now, the two user that show at top of the list, their full name was stored in data base with two spaces between first and last name.
left trim fixes the issue.
The above picture if a screen cap of the output from a report I've been making using t-SQL tables and views. Each column has two values the first being the current number and then following the forward slash is the difference value for each week. These numbers look great for most of my reports and yet as you can see the Total column seems to have a completely erroneous value for the difference.
This table was created using the following code
SELECT
ISNULL(a.[LRPR Biospecimen Consent], 'Missing') AS Consent,
CONVERT(varchar, a.Oppong) + ' / ' + CONVERT(varchar, a.Oppong - ISNULL(b.Oppong, 0)) AS Oppong,
CONVERT(varchar, a.Tousimis) + ' / ' + CONVERT(varchar, a.Tousimis - ISNULL(b.Tousimis, 0)) AS Tousimis,
CONVERT(varchar, a.Willey) + ' / ' + CONVERT(varchar, a.Willey - ISNULL(b.Willey, 0)) AS Willey,
CONVERT(varchar, a.Anderson) + ' / ' + CONVERT(varchar, a.Anderson - ISNULL(b.Anderson, 0)) AS Anderson,
CONVERT(varchar, a.Bacarra) + ' / ' + CONVERT(varchar, a.Bacarra - ISNULL(b.Bacarra, 0)) AS Bacarra,
CONVERT(varchar, a.McMahon) + ' / ' + CONVERT(varchar, a.McMahon - ISNULL(b.McMahon, 0)) AS McMahon
FROM
dbo.vw_RPT_Ourisman_BiospecimenConsentWithProvider_Pivot a
LEFT OUTER JOIN dbo.tbl_vw_RPT_Ourisman_BiospecimenConsentWithProvider_Pivot b
ON ...
Variants of this code (with just pathnames changed has given accurate total values for the numbers on both sides of the forward slash.I am a novice SQL user and I just can't seem to figure out why this code has stopped working.
Any helpful advice is much appreciated
EDIT
Below is the code used to create the dbo.vw_RPT_Ourisman_BiospecimenConsentWithProvider_Pivot Total values.
With T as ( SELECT [LRPR Biospecimen Consent], [Oppong, Bridget A] AS Oppong, [Tousimis, Eleni] AS Tousimis, [Willey, Shawna] AS Willey, [Anderson, Lyndsay] AS Anderson,
[Bacarra, Minna Manalo] AS Bacarra, [McMahon, Ann] AS McMahon
FROM vw_RPT_Ourisman_BiospecimenConsentWithProvider_List c PIVOT (count([Breast Provider]) FOR [Breast Provider] IN ([Oppong, Bridget A], [Tousimis, Eleni],
[Willey, Shawna], [Anderson, Lyndsay], [Bacarra, Minna Manalo], [McMahon, Ann])) piv
WHERE [LRPR Biospecimen Consent] IS NOT NULL)
SELECT *
FROM T
UNION ALL
SELECT 'Total', SUM(Oppong), SUM(Tousimis), SUM(Willey), SUM(Anderson), SUM(Bacarra), SUM(McMahon)
FROM T