How can I use column reference in REGEXP_REPLACE in Oracle? - database

My script looks like this :
SELECT
regexp_replace(column1,'"resId":([^"]+?)..','"resId":column2,"')
FROM
table;
Here, I need to replace resId value in column1 by value from column2.

It is hard to tell without the sample data and expected output what you exactly want.
It appears you are expecting to transform a pattern like this - "resId":Value1,"otherid":othervalue
Please note I took into consideration that a key value pair of
"resID":value exists in the data and there is a separator ( a space or a comma) between such key-value pairs.
(,|$) indicates a comma separator or end of line after the value. You may change this to contain any separator in your data that distinguishes it from other combinations. If there is no such thing and the data is purer than this, you should care to describe it clearly by editing your question, which may help us to provide you a proper solution.
SQL Fiddle
Query:
SELECT column1,
column2,
regexp_replace(column1,'"resId":[^"]+(,|$)','"resId":' || column2 || '\1') as replaced
FROM t
Results:
| COLUMN1 | COLUMN2 | REPLACED |
|-------------------------------------|---------|-------------------------------------|
| "resId":Value1,"otherid":othervalue | Value2 | "resId":Value2,"otherid":othervalue |
| "otherid":othervalue,"resId":Value1 | Value2 | "otherid":othervalue,"resId":Value2 |

Concatenate the column2 value into your replacement string:
SELECT regexp_replace(
column1,
'"resId":([^"]+?),"','"resId":' || column2 || ',"'
)
FROM table;
However, if you data is well-formed JSON and the "resId" value will be a simple literal (not an array or an object) then you can use a regular expression that would parse this like:
'("resId":)(null|true|false|(-?0|[1-9]\d*)(\.\d*)?([eE][+-]?\d+)?|"(\\["\/bfrnt]|\\u\d{4}|[^"\/'||CHR(8)||CHR(9)|| CHR(10)||CHR(12)||CHR(13)||'])*")'
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( column1, column2 ) AS
SELECT '{"resId":null}', 1 FROM DUAL UNION ALL
SELECT '{"resId":true}', 2 FROM DUAL UNION ALL
SELECT '{"resId":false}', 3 FROM DUAL UNION ALL
SELECT '{"resId":123}', 4 FROM DUAL UNION ALL
SELECT '{"resId":""}', 5 FROM DUAL UNION ALL
SELECT '{"resId":"\r\n"}', 6 FROM DUAL UNION ALL
SELECT '{"resId":"test"}', 7 FROM DUAL UNION ALL
SELECT '{"resId":"' || CHR(13) || CHR(10) || '"}', 8 FROM DUAL;
Query 1:
SELECT column1,
column2,
regexp_replace(
column1,
'("resId":)(null|true|false|(-?0|[1-9]\d*)(\.\d*)?([eE][+-]?\d+)?|"(\\["\/bfrnt]|\\u\d{4}|[^"\/'||CHR(8)||CHR(9)|| CHR(10)||CHR(12)||CHR(13)||'])*")',
'\1' || column2
) As repl
FROM table_name
Results:
| COLUMN1 | COLUMN2 | REPL |
|------------------|---------|----------------|
| {"resId":null} | 1 | {"resId":1} |
| {"resId":true} | 2 | {"resId":2} |
| {"resId":false} | 3 | {"resId":3} |
| {"resId":123} | 4 | {"resId":4} |
| {"resId":""} | 5 | {"resId":5} |
| {"resId":"\r\n"} | 6 | {"resId":6} |
| {"resId":"test"} | 7 | {"resId":7} |
| {"resId":" | 8 | {"resId":" | -- Note: not well-formed JSON
| "} | | "} | -- so did not get matched.

Related

Get all course, chapter in one column SQL Server

Course
+-----+----------+
| id | c_name |
+-----+----------+
| 1 | course1 |
| 7 | course2 |
+-----+----------+
Chapter
+-----+----------+------------+
| id | Ch_name | c_id |
+-----+----------+------------+
| 3 | Chapter1 | 1 |
| 9 | Chapter2 | 7 |
| 11 | Chapter3 | 1 |
| 17 | Chapter4 | 1 |
+-----+----------+------------+
I'm trying to select all data so that I can generate the following output:
+-----+-- |
|Course |
+-----+-- |
|Course1 |
|Chapter1 |
|Chapter3 |
|Chapter4 |
| |
|Course2 |
|Chapter2 |
I have tried in this way:
select
c.CourseID ,
'Course' as table_name,
c.CourseName as Course,
'' as Chapter
from [MstCourse]c
union
select
s.CourseID,
'Chapter' as table_name,
c.CourseName as Course,
s.ChapterName as Chapter
from [MstCourse] c
inner JOIN [ManageChapter] s ON c.CourseID= s.CourseID
order by Course, Chapter
But I am not getting the results in a single column.
You could achieve this with a group by ... with rollup clause.
Sample data
create table course
(
id int,
name nvarchar(10)
);
insert into course(id, name) values
(1, 'Course1'),
(7, 'Course2');
create table chapter
(
id int,
name nvarchar(10),
c_id int
);
insert into chapter(id, name, c_id) values
(3 , 'Chapter1', 1),
(9 , 'Chapter2', 7),
(11, 'Chapter3', 1),
(17, 'Chapter4', 1);
Solution
select coalesce(ch.Name, co.Name) as [Course]
from course co
join chapter ch
on ch.c_id = co.id
group by co.Name, ch.Name with rollup
having grouping(co.Name) <> 1
order by co.Name, ch.Name;
For some background on how this solution works, have a look at this fiddle.

Select unique rows with where in clause (SQL Server)

I am trying to return one json per unique value in a column.
However, when I try to select from a sub-query the entire result set is returned.
Example Table
| json | column |
|--------|--------|
| {obj1} | 1 |
| {obj2} | 1 |
| {obj3} | 2 |
Example Query
select distinct
[json]
from someTable
where [column] in (
select distinct
[column]
from someTable
)
Actual Output
| json |
|--------|
| {obj1} |
| {obj2} |
| {obj3} |
Expected Output
| json |
|--------|
| {obj1} |
| {obj3} |
How can I select just 1 json per unique column value?
If doesn't Matter output Related To Column is obj1 Or obj2 you must Use Group By Like this :
SELECT
Min(JSon) AS Json ,Column
FROM
someTable
Group By column
If you want the 1st [json] of each column then use row_number():
select t.[json] from (
select
[json],
row_number() over (partition by column order by id) rn
from someTable
) t
where t.rn = 1

How to merge multiple column into one column with same table in SQL Server?

I need to merge some column value into one column with varchar/nvarchar data type.
I tried to use Computed Column Specification in Table Designer, but I only know how to compute int data type.
| Column1 | | Column2 | | Column3 | |MergedColumn|
| A | | B | | C | | AB-C |
| A1 | | B1 | | C1 | | A1B1-C1 |
I need that result in MergedColumn.
The CONCAT function should work here:
SELECT
Column1,
Column2,
Column3,
CONCAT(Column1, Column2, '-', Column3) AS MergedColumn
FROM yourTable;

Distinct 2 field AS one column SQL SERVER

can i SELECT distinct 2 fields (provfrom, provto) on table AS one column
with condition :
- values of 2 fields is never same in one row
- values in field provfrom can be inside field provto but in different row
- values in field provto can be inside field provfrom but in different row
example :
i have 2 column as below
-------------------------
| provfrom | provto |
-------------------------
| 2 | 4 |
| 3 | 7 |
| 3 | 7 |
| 5 | 2 |
| 5 | 2 |
| 7 | 2 |
| 7 | 2 |
| 1 | 5 |
| 2 | 5 |
| 2 | 8 |
| 5 | 8 |
-------------------------
the result that i want by disticnt is as below
-------------
| prov |
-------------
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 7 |
| 8 |
-------------
Can i do this in sql server?
i try to found out by explore google, but not found it
Thanks
You can use Union keyword which will give distinct elements from Both Tables
select provfrom from mytable
union
select provTo from mytable
You can either do this with a union or by using apply, the apply has less IO so I would go with the apply query.
create table #temp
(
provfrom tinyint,
provto tinyint
);
insert into #temp (provfrom, provto)
values (2,4),(3,7),(3,7),
(5,2),(5,2),(7,2),
(7,2),(1,5),(2,5),
(2,8),(5,8);
set statistics io on;
select distinct
a.provfromto
from #temp as t
cross apply (values (t.provfrom),(t.provto)) as a(provfromto);
select provfrom from #temp
union
select provTo from #temp
set statistics io off;
drop table #temp;
Try this:
select t.prov
from
(select provfrom as prov
from yourtable
union
select provto
from yourtable) as t
order by t.prov
UNION function apply a distinct clause, so you'll get all value per one occurence.
The external query about ordering your result set

Sort String Containing number

Current OutPut:
PM_DIG_OUTPUT_1_CLOSED
PM_DIG_OUTPUT_10_CLOSED
PM_DIG_OUTPUT_14_CLOSED
PM_DIG_OUTPUT_15_CLOSED
PM_DIG_OUTPUT_16_CLOSED
PM_DIG_OUTPUT_2_CLOSED
PM_DIG_OUTPUT_3_CLOSED
Expected Output:
PM_DIG_OUTPUT_1_CLOSED
PM_DIG_OUTPUT_2_CLOSED
PM_DIG_OUTPUT_3_CLOSED
PM_DIG_OUTPUT_10_CLOSED
PM_DIG_OUTPUT_14_CLOSED
PM_DIG_OUTPUT_15_CLOSED
PM_DIG_OUTPUT_16_CLOSED
Index of Number is not fixed
What is the best way to achieve this order?
EDIT:
Some records also contain following data
PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO1
PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO2
PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO3
PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO4
Query:
SQLFIDDLEExample
SELECT *
FROM Table1 t1
ORDER BY CAST(REPLACE(REPLACE(col, 'PM_DIG_OUTPUT_', ''),'_CLOSED', '') AS int)
Result:
| COL |
|-------------------------|
| PM_DIG_OUTPUT_1_CLOSED |
| PM_DIG_OUTPUT_2_CLOSED |
| PM_DIG_OUTPUT_3_CLOSED |
| PM_DIG_OUTPUT_10_CLOSED |
| PM_DIG_OUTPUT_14_CLOSED |
| PM_DIG_OUTPUT_15_CLOSED |
| PM_DIG_OUTPUT_16_CLOSED |
EDITED ANSWER
You could use query:
SQLFIDDLEExample
SELECT *
FROM Table1 t1
ORDER BY CASE WHEN LEFT(col, 2) = 'PM'
THEN CAST(REPLACE(REPLACE(col, 'PM_DIG_OUTPUT_', ''),'_CLOSED', '') AS int)
ELSE RIGHT(col,1) END
Result:
| COL |
|-----------------------------------------------|
| PM_DIG_OUTPUT_1_CLOSED |
| PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO1 |
| PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO2 |
| PM_DIG_OUTPUT_2_CLOSED |
| PM_DIG_OUTPUT_3_CLOSED |
| PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO3 |
| PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO4 |
| PM_DIG_OUTPUT_10_CLOSED |
| PM_DIG_OUTPUT_14_CLOSED |
| PM_DIG_OUTPUT_15_CLOSED |
| PM_DIG_OUTPUT_16_CLOSED |
Assuming that after the number there's only one underscore and some text (then no matter what is before the number, if it's at least one underscore and some text).
Edit for new values. It will sort by the numbers if it can find them and won't break if no numbers were found by matching the pattern:
select
*,
substring(y,len(y)-charindex('_',reverse(y))+2,100) as num
from (
select
*,
substring(x,1,len(x)-charindex('_',reverse(x))) as y
from (
select 'PM_DIG_OUTPUT_1_CLOSED' as x union all
select 'PM_DIG_OUTPUT_10_CLOSED' union all
select 'PM_DIG_OUTPUT_14_CLOSED' union all
select 'PM_DIG_OUTPUT_15_CLOSED' union all
select 'PM_DIG_OUTPUT_16_CLOSED' union all
select 'PM_DIG_OUTPUT_2_CLOSED' union all
select 'PM_DIG_OUTPUT_3_CLOSED' union all
select 'PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO1' union all
select 'PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO2' union all
select 'PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO3' union all
select 'PRM_CODE_MIO_DIGITALOUT_WRITE_LOGIC_CARD2_DO4'
) x
) y
order by
case when isnumeric(substring(y,len(y)-charindex('_',reverse(y))+2,100))=1 then cast(substring(y,len(y)-charindex('_',reverse(y))+2,100) as int) end

Resources