1

I have to split the resolution something like below:

declare @t table (resolution nvarchar(100))

Insert into @t values ('1366 X 768 @ 60 Hz'),
('1024 X 768 @ 60 Hz'),
('640 X 480 @ 70 Hz')

I want the output as

Fst   |  Snd  | Thd  
------+-------+-----------
1366  |  768  |  60 Hz  
1024  |  768  |  60 Hz  
640   |  480  |  70 HZ

I have tried this query

select 
    *,
    substring(resolution, 1, charindex('X', resolution) - 1) as fst,
    substring(resolution, charindex('X', resolution) + 1, charindex('@', resolution) + 1) as snd
from 
    @t

But it is not returning the correct output.

Can anyone please show me what is wrong in here?

1
  • The third argument to substring is the length, not the end of the substring to be returned. charindex('@', resolution) + 1 is not the length of the vertical resolution ('768'). Commented Sep 7, 2019 at 18:32

6 Answers 6

4

You can also try PARSENAME() function if there are only 3 part every time, and data format always as you shown.

SELECT 
PARSENAME(REPLACE(REPLACE(resolution,' X ','.'),' @ ','.') ,3) Fst,
PARSENAME(REPLACE(REPLACE(resolution,' X ','.'),' @ ','.') ,2) Snd,
PARSENAME(REPLACE(REPLACE(resolution,' X ','.'),' @ ','.') ,1) Thd
FROM @t

Output is-

Fst     Snd     Thd
1366    768     60 Hz
1024    768     60 Hz
640     480     70 Hz

If you wants to exlude ' Hz' from the Thd column, Just do it-

SELECT 
PARSENAME(REPLACE(REPLACE(REPLACE(resolution,' X ','.'),' @ ','.'),' Hz','') ,3) Fst,
PARSENAME(REPLACE(REPLACE(REPLACE(resolution,' X ','.'),' @ ','.'),' Hz','')  ,2) Snd,
PARSENAME(REPLACE(REPLACE(REPLACE(resolution,' X ','.'),' @ ','.'),' Hz','')  ,1) Thd
FROM @t
Sign up to request clarification or add additional context in comments.

4 Comments

That will return 'Hz' in the third column. Rethink and edit your answer.
@Sami nope, you can check the output I just added.
My bad didn't notice the desired results include 'Hz' in the OP Q
Whats the issue? Hz is OP's requirement. Whats problem here?
3

Here you go

declare @t table (resolution nvarchar(100))

Insert into @t values ('1366 X 768 @ 60 Hz'),
('1024 X 768 @ 60 Hz'),
('640 X 480 @ 70 Hz');

SELECT LEFT(Resolution, CHARINDEX('X', Resolution) - 1) [1St],
       SUBSTRING(Resolution, CHARINDEX('X', Resolution)+1, CHARINDEX('@', Resolution)-
       CHARINDEX('X', Resolution)-2) [2nd],
       SUBSTRING(Resolution, CHARINDEX('@', Resolution)+1, CHARINDEX('H', Resolution)-
       CHARINDEX('@', Resolution)-2) [3rd]
FROM @t;

Online demo

Or more better(without white spaces)

SELECT LEFT(Resolution, CHARINDEX('X', Resolution) - 2) [1St],
       SUBSTRING(Resolution, 
                 CHARINDEX('X', Resolution)+2, 
                 CHARINDEX('@', Resolution)- CHARINDEX('X', Resolution)-3
                ) [2nd],
       SUBSTRING(Resolution, 
                 CHARINDEX('@', Resolution)+2, 
                 CHARINDEX('H', Resolution) - CHARINDEX('@', Resolution)-3
                ) [3rd]
FROM @t

If you want 'Hz' to be in the third column then

SELECT LEFT(Resolution, CHARINDEX('X', Resolution) - 2) [1St],
       SUBSTRING(Resolution, 
                 CHARINDEX('X', Resolution)+2, 
                 CHARINDEX('@', Resolution)- CHARINDEX('X', Resolution)-3
                ) [2nd],
       SUBSTRING(Resolution, 
                 CHARINDEX('@', Resolution)+2, 
                 LEN(Resolution)
                ) [3rd]
FROM @t;

Also, you could use PARSENMAE() function (as mkrabbani provide)to return both results as the following:

  • With 'Hz'

    SELECT Resolution,
           PARSENAME(Res, 3) Fst,
           PARSENAME(Res, 2) Snd,
           PARSENAME(Res, 1) Thd
    FROM
    (
      VALUES
      ('1366 X 768 @ 60 Hz'),
      ('1024 X 768 @ 60 Hz'),
      ('640 X 480 @ 70 Hz')
    ) T(Resolution) 
    CROSS APPLY 
    (
      SELECT REPLACE(REPLACE(T.Resolution, ' X ', '.'), ' @ ', '.') Res
    ) TT;
    
  • Without 'Hz':

    SELECT Resolution,
           PARSENAME(Res, 3) Fst,
           PARSENAME(Res, 2) Snd,
           PARSENAME(Res, 1) Thd
    FROM
    (
      VALUES
      ('1366 X 768 @ 60 Hz'),
      ('1024 X 768 @ 60 Hz'),
      ('640 X 480 @ 70 Hz')
    ) T(Resolution) 
    CROSS APPLY 
    (
      SELECT REPLACE(REPLACE(REPLACE(T.Resolution, ' X ', '.'), ' @ ', '.'), 'Hz', '') Res
    ) TT;
    

Demo for the last 3 queries.

Comments

2

You can use PARSENAME function to split :

SELECT *,
    PARSENAME(REPLACE(PARSENAME(REPLACE(resolution,'@','.'),2),'X','.'),2) 'Fst' ,
    PARSENAME(REPLACE(PARSENAME(REPLACE(resolution,'@','.'),2),'X','.'),1) 'Snd' ,
    PARSENAME(REPLACE(resolution,'@','.'),1) 'Thd'
FROM @t 

Comments

1

You can use this :

select 
    *,
    substring(resolution, 1, charindex('X', resolution) - 1) as fst,
    substring(resolution, charindex('X', resolution) + 1, charindex('@', resolution) - charindex('X', resolution)-1) as snd ,
    substring(resolution, charindex('@', resolution) + 1,len(resolution) -  charindex('@', resolution)  ) as thr
from 
    @t

Comments

1

A bit cleaner code using APPLY

SELECT LEFT(Resolution, idx1 - 2) [1St],
       SUBSTRING(Resolution, idx1 + 2, idx2 - idx1 - 3) [2nd],
       SUBSTRING(Resolution, idx2 + 2, CHARINDEX('H', Resolution) - idx2 - 3) [3rd]
FROM @t
CROSS APPLY (
     SELECT CHARINDEX('X', Resolution) idx1
          , CHARINDEX('@', Resolution) idx2) i 

Comments

1

And since no string parsing post would be complete without an XML based solution:

SELECT ResXml.value(N'/x[1]', 'nvarchar(100)') As Fst,  
       ResXml.value(N'/x[2]', 'nvarchar(100)') As Snd, 
       ResXml.value(N'/x[3]', 'nvarchar(100)') As Thd
FROM
(
    SELECT CAST('<x>'+ REPLACE(REPLACE(resolution, ' X ', '</x><x>'), ' @ ', '</x><x>') + '</x>' As Xml) As ResXml
    FROM @t
) As x

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.