How add separating blank space in numeric value - sql

Unfortunately I couldn't find solutions in the docs.
I want to get numbers in specific format, like this:
234652.24 --> 234 652.24
42145124 --> 42 145 124
select employee_id, to_char(salary, '??????') as "Salary
from employees;

You can specify the NLS_NUMERIC_CHARTACTERS setting as part of the TO_CHAR() call, and use the G and D format model placeholders:
with employees (employee_id, salary) as (
select 1, 234652.24 from dual --> 234 652.24
union all select 2, 42145124 from dual --> 42 145 124
)
select employee_id,
to_char(salary, '999G999G999D99', 'NLS_NUMERIC_CHARACTERS=''. ''') as "Salary"
from employees;
EMPLOYEE_ID Salary
----------- ---------------
1 234 652.24
2 42 145 124.00
If you don't want the trailing zeros in the second value you can add the FM format modifier, which also removes the leading space (which is there to allow for a minus sign if there are any negative values); but that still leaves the trailing period; you can use RTRIM() to get rid of that:
with employees (employee_id, salary) as (
select 1, 234652.24 from dual --> 234 652.24
union all select 2, 42145124 from dual --> 42 145 124
)
select employee_id,
rtrim(to_char(salary, 'FM999G999G999D99', 'NLS_NUMERIC_CHARACTERS=''. '''), '.') as "Salary"
from employees;
EMPLOYEE_ID Salary
----------- ---------------
1 234 652.24
2 42 145 124

You definitely should read about NLS_NUMERIC_CHARACTERS at https://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_options072.htm

for example,
to_char( 1485, '9g999') ' 1 485'
to_char( 148.5, '999.999') ' 148.500'
to_char( 148.5, '999d999') ' 148,500'
to_char( 3148.5,'9g999d999') ' 3 148,500'

I tried following query and the output is displayed in specified format
mysql> select format(id, '## ###') from test;
+----------------------+
| format(id, '## ###') |
+----------------------+
| 123,456 |
| 123,456,789 |
| 1 |
| 10 |
| 10,000 |
+----------------------+
5 rows in set, 5 warnings (0.00 sec)

Related

How get all value in same row without using multiple joins conditions in SQL?

I have below table structures
Student
Stud_ID | First_Name | Last_name | Contact
ID001 | AAA | AAA | 111
ID002 | BBB | BBB | 222
StudUser
Stud_ID | NUM | Value
ID001 | 10 | English
ID001 | 20 | Math
ID001 | 30 | Science
ID002 | 10 | English
ID002 | 20 | Math
Expected Output
Stud_id | First_name | 10 | 20 | 30
ID001 | AAA | English | Math | Science
ID002 | BBB | English | Math |
Current query I'm using
select
stud_id,
First_name,
EG.EGUV AS "10",
LE.LEUV AS "20",
FPS.FPSUV AS "30"
from
student,
(SELECT STUD_ID AS EGS,USER_VALUE AS EGUV FROM STUD_USER WHERE COL_NUM='10') AS EG,
(SELECT STUD_ID AS BUS,USER_VALUE AS BUUV FROM STUD_USER WHERE COL_NUM='20') AS BU,
(SELECT STUD_ID AS AUS,USER_VALUE AS AUV FROM STUD_USER WHERE COL_NUM='30') AS A
where
ST.STUD_ID=EG.EGS(+) and
ST.STUD_ID=BU.BUS(+) and
ST.STUD_ID=A.AUS(+)
Please let me know if there is any other optimized way to get all user Values.
Note : this table structure cannot be altered only read permission is available
You can use the Oracle PIVOT clause for this.
It will (sort of) dynamically create additional columns according to values of a selected column.
This is the query I used (using WITH clauses to simulate your input data):
WITH
Student
AS
(SELECT 'ID001' AS Stud_ID, 'AAA' AS First_Name, 'AAA' AS Last_name, 111 AS Contact FROM DUAL
UNION ALL
SELECT 'ID002', 'BBB', 'BBB', 222 FROM DUAL),
StudUser
AS
(SELECT 'ID001' AS Stud_ID, 10 AS NUM, 'English' AS VALUE FROM DUAL
UNION ALL
SELECT 'ID001', 20, 'Math' FROM DUAL
UNION ALL
SELECT 'ID001', 30, 'Science' FROM DUAL
UNION ALL
SELECT 'ID002', 10, 'English' FROM DUAL
UNION ALL
SELECT 'ID002', 20, 'Math' FROM DUAL),
Prepare
AS
(SELECT ST.STUD_ID,
ST.FIRST_NAME,
SU.NUM,
SU.VALUE
FROM STUDENT ST LEFT JOIN STUDUSER SU ON ST.STUD_ID = SU.STUD_ID)
SELECT *
FROM Prepare PIVOT (MIN (VALUE) FOR NUM IN (10, 20, 30))
The PIVOT function expects an aggregate function, because it will go over all of the results where e.g. STUD_ID = ID001 and NUM = 10 and will return a value according to the aggregate function that was used. Your example implies the combination of STUD_ID and NUM will be unique for the StudUser table, therefore most of the Oracle's aggregate functions will do, as they will have to go over just one value. If the combination wasn't unique, you would have to take a second to think about a way you would like to aggregate them.
The FOR section of the pivot clause lets you specify which values you would like to turn into columns. This, unfortunately cannot be generated dynamically, e.g.:
SELECT *
FROM Prepare PIVOT (MIN (VALUE) FOR NUM IN ( SELECT DISTINCT NUM FROM StudUser ))
That would be invalid and wouldn't compile.
You can also specify desired column names for the pivoted columns, like so:
SELECT *
FROM Prepare PIVOT (MIN (VALUE) FOR NUM IN (10 Subject1, 20 Subject2, 30 Subject3))
I found the PIVOT clause merely by searching: oracle turn values into columns, so I kinda guess you didn't find it because you weren't sure how to call this. Can't blame you.

BigQuery get all values in a range

I have a column that can contains a range and I want to get all values in that range. I.e
I have the following records
id | number
-------------
1 | 342-345
-------------
2 | 346
And a want it in the following format:
id | number
-------------
1 | 342
| 343
| 344
| 345
-------------
2 | 346
I am using Standard SQL.
You can use split() to split the string and then generate_array() to get the values you want:
select t.*,
GENERATE_ARRAY(cast(split(numbers, '-')[ordinal(1)] as int64),
cast(COALESCE(split(numbers, '-')[SAFE_ORDINAL(2)], split(numbers, '-')[ordinal(1)]) as int64),
1)
from (select 1 as id, '342-345' as numbers UNION ALL
SELECT 2, '346'
) t;

Convert String into Numeric, pulling from the left of ":" and then pulling to the right of ":"

Text_value is column with string values. I need to look for ONLY ':' and separate the left from the right and convert to numeric so I can perform an easy calculation. If ':' does not exist I want nulls to return. I am creating a view in Oracle SQL Developer
Text_Value (Column)
124
7
55:20
73:00
106:24
This is my code:
to_number(REGEXP_SUBSTR(b.text_value,'[^:]*',1,1)) AS Num,
to_number(REGEXP_SUBSTR(B.text_value,'[^:]*$')) AS FRACTION2
These are my results:
I would expect text_values that didn't contain ":" to return as null. That is what I would like to see.
You can check for a two numbers separated by a colon using the regular expression ^(\d+):(\d+)$ like this:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( text_value ) AS
SELECT '124' FROM DUAL UNION ALL
SELECT '7' FROM DUAL UNION ALL
SELECT '55:20' FROM DUAL UNION ALL
SELECT '73:00' FROM DUAL UNION ALL
SELECT '106:24' FROM DUAL;
Query 1:
SELECT text_value,
TO_NUMBER( REGEXP_SUBSTR( text_value, '^(\d+):(\d+)$', 1, 1, NULL, 1 ) ) AS num,
TO_NUMBER( REGEXP_SUBSTR( text_value, '^(\d+):(\d+)$', 1, 1, NULL, 2 ) ) AS fraction2
FROM table_name
Results:
| TEXT_VALUE | NUM | FRACTION2 |
|------------|--------|-----------|
| 124 | (null) | (null) |
| 7 | (null) | (null) |
| 55:20 | 55 | 20 |
| 73:00 | 73 | 0 |
| 106:24 | 106 | 24 |
You could avoid regular expressions and use instr and substr instead:
select text_value,
to_number(case when instr(text_value, ':') > 0
then substr(text_value, 1, instr(text_value, ':') - 1)
else null end) as num,
to_number(case when instr(text_value, ':') > 0
then substr(text_value, instr(text_value, ':') + 1)
else null end) as fraction2
from b;
That's doing more individual function calls, but they may still perform better than regular expressions, and you could move the instr into an inline view if you wanted to, so you aren't doing that four times (though the optimiser might cache the result anyway).
SQL Fiddle demo using a few of the values from your image plus a couple of other variations you didn't refer to, and which you might want to handle differently.
If those are not handled as you want, you can adjust the case expression conditions, e.g. for num changing to > 1, and for fraction2 comparing with the string length - but it depends what you want to see (and if those scenarios can even exist).
You're nearly there. You just need to test to see if the string has a : in it before extracting the 'seconds' portion of the string:
SELECT TEXT_VALUE,
TO_NUMBER(REGEXP_SUBSTR(text_value,'[^:]*',1,1)) AS MINUTES,
CASE
WHEN INSTR(TEXT_VALUE, ':') > 0 THEN TO_NUMBER(REGEXP_SUBSTR(text_value,'[^:]*$'))
ELSE NULL
END AS SECONDS
FROM T;
TEXT_VALUE MINUTES SECONDS
11 11 (null)
00:38 0 38
(null) (null) (null)
69:18 69 18
74:11 74 11
83:43 83 43
00:51 0 51
00:45 0 45
01:42 1 42
7 7 (null)
78:30 78 30
50 50 (null)
03:08 3 8
70:42 70 42
72:24 72 24
123 123 (null)
55:20 55 20
SQLFiddle here
EDIT
You can get rid of the CASE if you change the second regular expression to include, rather than exclude, the colon, then use SUBSTR to grab all characters following the ::
SELECT TEXT_VALUE,
TO_NUMBER(REGEXP_SUBSTR(text_value,'[^:]*',1,1)) AS MINUTES,
SUBSTR(REGEXP_SUBSTR(text_value, ':.*$'), 2) AS SECONDS3
FROM T;
Revised SQLFiddle here

PL/SQL to find Special Characters in multiple columns and tables

I am trying to come up with a script that we can use to locate any special characters that may exist in a column of data except for period, dash or underscore, and using variables.
My Data - Employees table:
---------------------------------------------------------
ID | LASTFIRST | LAST_NAME | FIRST_NAME | MIDDLE_NAME
---------------------------------------------------------
57 | Miller, Bob | Miller | &^$#*)er | NULL
58 | Smith, Tom | Smith | Tom | B
59 | Perry, Pat | Perry | P. | Andrew
My Script:
VAR spchars VARCHAR
spchars := '!#$%&()*+/:;<=>?#[\\\]^`{}|~'
select *
from (select dcid, LastFirst, Last_Name, First_Name, middle_name,
CASE WHEN REGEXP_LIKE(First_Name, '[ || spchars || ]*$' )
THEN '0' ELSE '1' END AS FNSPC
from employees)
where FNSPC = '0';
/
And all rows are returned.
Any idea what I am doing wrong here? I want to only select Bob Miller's row.
REGEXP, Schmegexp! ;-)
select * from employees
where translate (first_name, 'x!#$%&()*+/:;<=>?#[\]^`{}|~', 'x') != first_name;
That translates all the special characters to nothing, i.e. removes them from the string - hence changing the string value.
The 'x' is just a trick because translate doesn't work as you'd like if the 3rd parameter is null.

Regular Expression - Get specific group value in SQL

I have the following regular expression problem.
Input:
123_321_009
3111_00_001
5123_123
555
666_A66
777_B77_777
Output request as below:
123_321
3111_00
5123
555
666_A66
777_B77
Is there any way to get the value of the output above?
I tried below statement but lack the idea how to get the value i needed.
^(.*?)\\s?([_0-9])?$
Value appearing after the last underscore are not needed.
You can use REGEXP_REPLACE to remove the numbers following/including the last underscore.
SQL Fiddle
Query:
with x(y) as (
select '123_321_009' from dual union all
select '3111_00_001' from dual union all
select '5123_123' from dual union all
select '666_A66' from dual union all
select '777_B77_777' from dual union all
select '555' from dual
)
select y, regexp_replace(y,'_\d+$') substr
from x
Results:
| Y | SUBSTR |
|-------------|---------|
| 123_321_009 | 123_321 |
| 3111_00_001 | 3111_00 |
| 5123_123 | 5123 |
| 666_A66 | 666_A66 |
| 777_B77_777 | 777_B77 |
| 555 | 555 |
Pattern:
_ --matches an underscore
\d+ --matches one or more numbers
$ --matches end of the string
Effectively, this matches all the digits following/including the last underscore. Third parameter is regexp_replace is omitted. So, the pattern is
removed and replaced by nothing.
Since you a using Oracle, you can use a regex_replace(val,pattern,'') function with this pattern.
The following patterns would satisfy the samples you provided:
_[0-9]{3}$
_[0-9]*$
Here is a demonstration of this approach using SQL*Plus:
SCOTT#dev> WITH tab(num_val) AS
2 ( SELECT '123_321_009' FROM dual
3 UNION ALL
4 SELECT '3111_00_001' FROM dual
5 UNION ALL
6 SELECT '5123_123' FROM dual
7 UNION ALL
8 SELECT '555' FROM dual
9 )
10 SELECT tab.num_val,
11 regexp_replace(tab.num_val,'_[0-9]{3}$') approach_1,
12 regexp_replace(tab.num_val,'_[0-9]*$') approach_2
13 FROM tab
14 /
NUM_VAL APPROACH_1 APPROACH_2
=========== ====================== ==================
123_321_009 123_321 123_321
3111_00_001 3111_00 3111_00
5123_123 5123 5123
555 555 555
If you provided a larger sampling (or a more specific rule), a more specific solution could be provided.