How to split the string in one column into two columns - mysql

I have a table like this
id value
------- ---------------
1 ind.kolkatta
2 ind.pune
3 ind.mumbai
4 pak.lahore
5 pak.karachi
6 uae.sharjah
I want to return the following table:
id contry place
------- --------- ----------
1 ind kolkatta
2 ind pune
3 ind mumbai
4 pak lahore
5 pak karachi
6 uae sharjah
how can i do that using MSSQL.? I have already done in MYSQL using SUBSTRING_INDEX function
My MySql query
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(`value`, '.', 1), '.', -1) as contry,
SUBSTRING_INDEX(SUBSTRING_INDEX(`value`, '.', 2), '.', -1) as place
FROM `table`

Try following query:-
SELECT ID, SUBSTRING(value, 1, CHARINDEX('.', value)-1) AS contry,
SUBSTRING(value, CHARINDEX(',', value)+1, LEN(value)) AS place
FROM YOUR_TABLE;
This might be helpful to you.

Hope the Below Query helps you.
SELECT id, SUBSTRING(value,1,3) as Country,SUBSTRING(value,4,LEN(value))AS Place FROM TableName

Try this:
SELECT Id,
LEFT(Value, CHARINDEX('.', Value)-1) AS Country,
STUFF(Value, 1, CHARINDEX('.', Value), '') AS Place
FROM Table
As per King King comment I checked the following
SELECT Id,
PARSENAME(value, 2) AS Country,
PARSENAME(Value, 1) AS Place
FROM Table
The above one worked, but I not sure about the version supported (I am using SSMS 2012).

Or just loop and it will parse out how ever many periods you have in your name.
DECLARE #FILE VARCHAR(55) = 'ind.kol.katta.test1.test2.test3.test4'
DECLARE #FILEFUN AS VARCHAR(55) = LEFT(#FILE,CHARINDEX('.',#FILE))
DECLARE #FILENAMEOUTPUT AS TABLE(Name Varchar(55))
WHILE LEN(#FILE) > 0
BEGIN
INSERT INTO #FILENAMEOUTPUT
SELECT REPLACE(#FILEFUN,'.','')
SET #FILE = REPLACE(#FILE,#FILEFUN,'')
SET #FILEFUN = iif(CHARINDEX('.',#FILE)=0,#FILE,LEFT(#FILE,CHARINDEX('.',#FILE)))
END
SELECT * FROM #FILENAMEOUTPUT

Related

Insert a "-" after third character for whole column in SQL

I have a column (Name is the header of the column) with 8 character numbers. I am looking for a query to insert a '-' after the third character of every row of data.
For example if I have:
| Name |
|----------|
| 99912345 |
I want to get:
| Name |
|-----------|
| 999-12345 |
I have tried the following:
SELECT INSERT(name, 3, 0, "-");
The database I am using is called temp.Test1 on mySQL
You were close:
SELECT INSERT(name, 4, 0, '-') from mytable
Here is the demo:
DEMO
In MySQL, use substring to divide your value and concat to put it back together.
set #test = 99912345;
select concat(
substring(#test, 1, 3),
'-',
substring(#test, 4)
);
gives 999-12345
Edit: You can also make a virtual column which does this for you, and just retrieve the column in your application.
alter table `test1`
add `formattedName` varchar(9) as (
concat(
substring(`name`, 1, 3),
'-',
substring(`name`, 4)
)
);
select `formattedName` from `test`
See demo

Postgres Returning HTML table tags grouped by column for resultset

I'm trying to construct a function that generates the row and cell HTML tags which will be used in another application to build a basic HTML table. The row and cells need to be grouped/concatenated by the region id. This is the part I'm currently struggling with.
I've tried to put the following function together, but not really sure where to go to ensure that the output is grouped correctly by the region_id.
This is not something I would generally do SQL, but I'm working with some limited technologies.
create table reporting
(
id integer,
region_id integer,
category text,
item text,
status text
);
insert into reporting values
(1, 1, 'audio', 'speakers', 'delivered'),
(2, 1, 'display', 'monitors', 'pending'),
(3, 2, 'cables', 'hdmi', 'pre-order'),
(4, 3, 'storage', 'sdd', 'cancelled'),
(5, 3, 'software', 'business', 'delivered'),
(6, 3, 'other', 'support', 'delivered');
create function html_out (query text)
returns TABLE(region_id text, result text) language plpgsql as $$
declare
rec record;
header boolean := true;
begin
for rec in
execute format($q$
select row_to_json(q) json_row
from (%s) q
$q$, query)
loop
return query select region_id,
format ('<tr><td>%s</td></tr>', string_agg(value, '</td><td>'))
from json_each_text(rec.json_row);
end loop;
end $$;
select html_out('select region_id, category, item, status from reporting');
You can use string aggregation. I think the logic you want is:
select
region_id,
'<tr><td>'
|| string_agg(concat_ws('</td><td>', category, item, status), '</td></tr><tr><td>')
|| '</td></tr>' html
from reporting
group by region_id
order by 1
Demo on DB Fiddle
region_id | html
--------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | <tr><td>audio</td><td>speakers</td><td>delivered</td></tr><tr><td>display</td><td>monitors</td><td>pending</td></tr>
2 | <tr><td>cables</td><td>hdmi</td><td>pre-order</td></tr>
3 | <tr><td>storage</td><td>sdd</td><td>cancelled</td></tr><tr><td>software</td><td>business</td><td>delivered</td></tr><tr><td>other</td><td>support</td><td>delivered</td></tr>
If this is about consolidating repeating region_id with rowspan=, then you can get that in one go like this:
with consolidate as (
select region_id, concat('<td rowspan="', count(*), '">') as rowspan
from reporting
group by region_id
), trows as (
select row_number() over (order by r.region_id, r.id) as rnum,
concat(
'<tr>',
case
when lag(c.region_id) over w = c.region_id then ''
else concat(c.rowspan, c.region_id, '</td>')
end,
'<td>',
array_to_string(array[r.category, r.item, r.status]::text[], '</td><td>', '</td>'),
'</tr>'
) as html
from consolidate c
join reporting r on r.region_id = c.region_id
window w as (partition by r.region_id order by r.id)
)
select array_to_string(array_agg(html order by rnum), '
')
from trows;
-[ RECORD 1 ]---+-----------------------------------------------------------------------------
array_to_string | <tr><td rowspan="2">1</td><td>audio</td><td>speakers</td><td>delivered</tr> +
| <tr><td>display</td><td>monitors</td><td>pending</tr> +
| <tr><td rowspan="1">2</td><td>cables</td><td>hdmi</td><td>pre-order</tr> +
| <tr><td rowspan="3">3</td><td>storage</td><td>sdd</td><td>cancelled</tr> +
| <tr><td>software</td><td>business</td><td>delivered</tr> +
| <tr><td>other</td><td>support</td><td>delivered</tr>
I put a newline in as the delimiter for that last array_to_string() just to get it to look nice. A ' ' or '' would probably be what you want.

Separate Columns with conditions

I have a table with some problem data. For example, the table is as follow :
ID NAME JOB
--- --------------------------- ---------------
1 Peter Teacher
2 John Programmer
3 Tom**He is a Teacher
4 Alan**He is a Accountant
The problem is some data has been correctly inserted but some hasn't. Now I want to execute an SQL in order to make the table looks like below :
ID NAME JOB
--- --------------------------- ---------------
1 Peter Teacher
2 John Programmer
3 Tom Teacher
4 Alan Accountant
I am not familiar with SQL Statement so I can just think of using the following PHP Script to fix this problem.
$sql1 = "SELECT NAME FROM MY_TABLE WHERE JOB = '' AND NAME LIKE '%He is a %'";
$res1 = mysql_query($sql1);
while($row1 = mysql_fetch_array($res1)){
$new_data = explode("**He is a ", $row1["NAME"]);
$sql2 = "UPDATE MY_TABLE SET NAME = '".$data[0]."', JOB = '".$data[1]."' WHERE ID = '".$data["ID"]."'";
mysql_query($sql2);
}
Can anyone suggest a better way for me to fix this problem with one or a few SQL Statement ? Thanks
UPDATE
SET NAME = SUBSTRING_INDEX(SUBSTRING_INDEX(NAME, '**He is a ', 1), ' ', -1),
job = SUBSTRING_INDEX(SUBSTRING_INDEX(NAME, '**He is a ', 2), ' ', -1)
WHERE NAME LIKE '%**He is a %'
You can use the substring_index function to break up the string, and apply all the changes in a single update statement:
UPDATE my_table
SET JOB = SUBSTRING_INDEX (name, '**He is a ', -1),
name = SUBSTRING_INDEX (name, '**He is a ', 1),
WHERE name LIKE '%**He is a %' AND
(job IS NULL OR job = '') -- Just to be on the safe side

SQL: select unique substrings from the table by mask

There is a SQL table mytable that has a column mycolumn.
That column has text inside each cell. Each cell may contain "this.text/31/" or "this.text/72/" substrings (numbers in that substrings can be any) as a part of string.
What SQL query should be executed to display a list of unique such substrings?
P.S. Of course, some cells may contain several such substrings.
And here are the answers for questions from the comments:
The query supposed to work on SQL Server.
The prefered output should contain the whole substring, not the numeric part only. It actually could be not just the number between first "/" and the second "/".
And it is varchar type (probably)
Example:
mycolumn contains such values:
abcd/eftthis.text/31/sadflh adslkjh
abcd/eftthis.text/44/khjgb ljgnkhj this.text/447/lhkjgnkjh
ljgkhjgadsvlkgnl
uygouyg/this.text/31/luinluinlugnthis.text/31/ouygnouyg
khjgbkjyghbk
The query should display:
this.text/31/
this.text/44/
this.text/447/
How about using a recursive CTE:
CREATE TABLE #myTable
(
myColumn VARCHAR(100)
)
INSERT INTO #myTable
VALUES
('abcd/eftthis.text/31/sadflh adslkjh'),
('abcd/eftthis.text/44/khjgb ljgnkhj this.text/447/lhkjgnkjh'),
('ljgkhjgadsvlkgnl'),
('uygouyg/this.text/31/luinluinlugnthis.text/31/ouygnouyg'),
('khjgbkjyghbk')
;WITH CTE
AS
(
SELECT MyColumn,
CHARINDEX('this.text/', myColumn, 0) AS startPos,
CHARINDEX('/', myColumn, CHARINDEX('this.text/', myColumn, 1) + 10) AS endPos
FROM #myTable
WHERE myColumn LIKE '%this.text/%'
UNION ALL
SELECT T1.MyColumn,
CHARINDEX('this.text/', T1.myColumn, C.endPos) AS startPos,
CHARINDEX('/', T1.myColumn, CHARINDEX('this.text/', T1.myColumn, c.endPos) + 10) AS endPos
FROM #myTable T1
INNER JOIN CTE C
ON C.myColumn = T1.myColumn
WHERE SUBSTRING(T1.MyColumn, C.EndPos, 100) LIKE '%this.text/%'
)
SELECT DISTINCT SUBSTRING(myColumn, startPos, EndPos - startPos)
FROM CTE
Having a table named test with the following data:
COLUMN1
aathis.text/31/
this.text/1/
bbbthis.text/72/sksk
could this be what you are looking for?
select SUBSTR(COLUMN1,INSTR(COLUMN1,'this.text', 1 ),INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 )+10) - INSTR(COLUMN1,'this.text', 1 )+1) from test;
result:
this.text/31/
this.text/1/
this.text/72/
i see your problem:
Assume the same table as above but now with the following data:
this.text/77/
xxthis.text/33/xx
xthis.text/11/xxthis.text/22/x
xthis.text/1/x
The following might help you:
SELECT SUBSTR(COLUMN1, INSTR(COLUMN1,'this.text', 1 ,1), INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 ,1)+10) - INSTR(COLUMN1,'this.text', 1 ,1)+1) FROM TEST
UNION
SELECT CASE WHEN (INSTR(COLUMN1,'this.text', 1,2 ) >0) THEN
SUBSTR(COLUMN1, INSTR(COLUMN1,'this.text', 1,2 ), INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 ,2),2) - INSTR(COLUMN1,'this.text', 1,2 )+1) end FROM TEST;
it will generate the following result:
this.text/1/
this.text/11/
this.text/22/
this.text/33/
this.text/77/
The downside is that you need to add a select statement for every occurance you might have of "this.text". If you might have 100 "this.text" in the same cell it might be a problem.
SQL> select SUBSTR(column_name,1,9) from tablename;
column_name
this.text
SELECT REGEXP_SUBSTR(column_name,'this.text/[[:digit:]]+/')
FROM table_name

Reformat table data sql

I have a field name with the following rows:
`name`
------
John Smith
George Washington
Ash Ketchum
Bill O'Reilly
I would like to reformat the rows on output:
`name`
------
SMITH, JOHN
WASHINGTON, GEORGE
KETCHUM, ASH
O'REILLY BILL
I know I can use upper( x.name ) for casing, but how can I reformat the names?
Assuming your rdbms is mySql, answer will need to be tailored to differenct dialects of sql.
SELECT concat( substring(name, locate(name, ' ')), ', ', substring(name, 0, locate(name, ' ') - 1)) FROM NAMES;
The real problem here however is data integrity. You need to have seperate columns for each peice of the name so that formating in the database is ensured to be consitent. Ideally you would want to be doing this --
Select concat(last_name, ', ', first_name) FROM NAMES;
Allowing
'name'
-------------------
John Smith
Smith, John
J Smith
Smith J
John q Smith
Jhon 'the smithmeister' Smith
All in the same column of a table is a bad thing for a number of reasons so this should be explictly prevented.
Try this:
SELECT SUBSTRING_INDEX( `name` , ' ', -1 ) + ', ' + SUBSTRING_INDEX( `name` , ' ', 1 )
FROM MyTable
#Ben, makes a good point about names with multiple spaces in them. I doubt this would give you the output you want in those cases, but it should get you started.
try this
SELECT Concat(SUBSTRING_INDEX( `name` , ' ', -1 ) , ', ' , SUBSTRING_INDEX( `name` , ' ', 1 )) as name
FROM your_Table