oracle regexp_substr to fetch string - sql

I have a sql query like
select count(distinct empno), count(distinct(deptno empname empid )) from emp
I want to fetch first occurrence of count and its content like:
count(distinct empno)
I have tried the following sql statement but its not working,
SQL >select regexp_substr('select count(distinct empno),
count(distinct(deptno)) from emp', 'count *( distinct .)')
from dual ;
REGEXP_SUBSTR('SELECTCOUNT(DISTINCTEMPNO),COUN
---------------------------------------------- count(distinct empno), count(distinct(deptno ))
I want output to return like :
REGEXP_SUBSTR('SELECTCOUNT(DISTINCTEMPNO)
count(distinct empno),
Regular expression should not match second ) closing bracket and it should match the 1st closing bracket.

* in your regex ates everything, you need to make the regex engine to match the shortest possibility.
count *\([^\)]\)(?=,)

Related

insert data in tree in oracle

I want to output table from tbl_ledger_input
My code is :
select parent_code ledger_code,
max(name) name,
4 depth,
max(CONCAT(SUBSTR(LEDGER_CODE,1,5),'0000')) PARENT_CODE,
select sum(balance) balance
from tbl_ledger_input
group by eff_date,
ledger_code,
balance,
ref_cur_id,
eff_date,
ref_branch,
cur_balance
order by eff_date,
ref_cur_id,
eff_date,
ref_branch,
sum(cur_balance) cur_balance,
number_date
from tbl_ledger_branch
where depth =5
group by parent_code,ref_cur_id,eff_date,ref_branch,number_date ;
I got this error :
ORA-00936: missing expression
Code you posted is somewhat messy;
select (in the 1st line) should be enclosed into parenthesis
I presume that next 3 lines also belong to it.
You can use a subquery, but it must return at most 1 row - otherwise you'll get too_many_rows error
Also, you can't use order by in there
This is code that might be OK (as far as syntax is concerned):
SELECT parent_code ledger_code,
MAX (name) name,
4 DEPTH,
MAX (CONCAT (SUBSTR (LEDGER_CODE, 1, 5), '0000')) PARENT_CODE,
( SELECT SUM (balance) balance
FROM tbl_ledger_input
GROUP BY eff_date,
ledger_code,
balance,
ref_cur_id,
eff_date,
ref_branch,
cur_balance)
-- order by eff_date , ref_cur_id , eff_date , ref_branch , sum(cur_balance) cur_balance , number_date
FROM tbl_ledger_branch
WHERE DEPTH = 5
GROUP BY parent_code,
ref_cur_id,
eff_date,
ref_branch,
number_date;
but - in my opinion - it is wrong. I doubt that subquery will actually return only one row, so - you'll get an error.
Therefore, use another option. Maybe
you should join tbl_ledger_input and tbl_ledger_branch
or, use queries separately (as subqueries or CTEs) and then merge the result
or, correlate subquery so that it really returns only one row
or something else

redshift regexp_substr all occurrences

I am trying to return all results that match a specific regex in Redshift database.
Sample query
WITH aa AS
(SELECT DISTINCT
id,
record,
regexp_substr(record, '(#{2})([A-Z]{2,3})',1,1),
REGEXP_COUNT(record, '(#{2})([A-Z]{2,3})')
FROM table_a)
SELECT
*
FROM aa
The above query returns the first occurrence and the total count of the occurrences.
Is there a way to return all occurrences? Maybe an iteration using a variable that is limited by the count?
regexp_substr(record, '(#{2})([A-Z]{2,3})',1,n)
There is a solution for Oracle with the CONNECT BY LEVEL, but that option seems to be unavailable for Redshift.
If I understand correctly, you can use split_part() instead:
split_part(record, '##', <n>)
Then you can attempt to generate numbers and get the results:
with n as (
select row_number() over () as n
from t
limit 10
)
select t.*, split_part(record, '##', n.n)
from t join
n
on split_part(record, '##', n.n) <> ''

Loop Through a Table to concatenate Rows

I have a table of similar structure:
Name Movies_Watched
A Terminator
B Alien
A Batman
B Rambo
B Die Hard
....
I am trying to get this:
Name Movies_Watched
A Terminator;Batman
B Alien, Die Hard, Rambo
My initial guess was:
SELECT Name, Movies_Watched || Movies_Watched from TABLE
But obviously that's wrong. Can someone tell me how can I loop through the 2nd column and concatenate them? What's the logic like?
Got to know that group_concat is the right approach. But haven't been able to figure it out yet. When I've tried:
select name, group_concat(movies_watched) from table group by 1
But it throws an error saying User-defined transform function group_concat must have an over clause
You are looking for string_agg():
select name, string_agg(movie_watched, ';') as movies_watched
from t
group by name;
That said, you are using Postgres, so you should learn how to use arrays instead of strings for such things. For instance, there is no confusion with arrays when the movie name has a semicolon. That would be:
select name, array_agg(movie_watched) as movies_watched
from t
group by name;
use array_agg
SELECT Name, array_agg(Movies_Watched)
FROM data_table
GROUP BY Name
i think you need listagg or group_concat as you are using vertica upper is postgrey solution
SELECT Name, listagg(Movies_Watched)
FROM data_table
GROUP BY Name
or
select Name,
group_concat(Movies_Watched) over (partition by Name order by name) ag
from mytable
As already mentioned, in Vertica it's LISTAGG():
WITH
input(nm,movies_watched) AS (
SELECT 'A','Terminator'
UNION ALL SELECT 'B','Alien'
UNION ALL SELECT 'A','Batman'
UNION ALL SELECT 'B','Rambo'
UNION ALL SELECT 'B','Die Hard'
)
SELECT
nm AS "Name"
, LISTAGG(movies_watched) AS movies_watched
FROM input
GROUP BY nm;
-- out Name | movies_watched
-- out ------+----------------------
-- out A | Terminator,Batman
-- out B | Alien,Rambo,Die Hard
-- out (2 rows)
-- out
-- out Time: First fetch (2 rows): 12.735 ms. All rows formatted: 12.776 ms

substring query

I want to get the substring out of a cell value wrt following eg-
Input: "J.H.Ambani.School"-----------School
Output: "H.Ambani"-----------------MidName
That is all the text that comes between the first and the last dots. Length of string or number of dots in string can be any. I am trying to form a query for above input column "School" to get the output column "MidName".What can be the sql query for it?
For Oracle Database:
SELECT
REGEXP_REPLACE(yourColumn, '^[^.]*.|.[^.]*$', '') AS yourAlias
FROM yourTable
If is correctly understood your problem by your statement
"That is all the text that comes between the first and the last dots". Then below is solution to your problem is as given below. Below is working solution in SQL SERVER, for other databases i could not check because of lack of time.
#SourceString : this is your input
#DestinationString : this is your output
declare #SourceString varchar(100)='J.H.Ambani.School'
declare #DestinationString varchar(100)
;with result as
(
select ROW_NUMBER()over (order by (select 100))SNO,d from(
select t.c.value('.','varchar(100)')as d from
(select cast('<a>'+replace(#SourceString,'.','</a><a>')+'</a>' as xml)data)as A cross apply data.nodes('/a') as t(c))B
)
select #DestinationString=COALESCE(#DestinationString+'.','')+ISNULL(d,'') from result where SNO>(select top 1 SNO from result order by SNO)
and SNO<(select top 1 SNO from result order by SNO desc)
select #DestinationString

Group rows with similar strings

I have searched a lot, but most of solutions are for concatenation option and not what I really want.
I have a table called X (in a Postgres database):
anm_id anm_category anm_sales
1 a_dog 100
2 b_dog 50
3 c_dog 60
4 a_cat 70
5 b_cat 80
6 c_cat 40
I want to get total sales by grouping 'a_dog', 'b_dog', 'c_dog' as dogs and 'a_cat', 'b_cat', 'c_cat' as cats.
I cannot change the data in the table as it is an external data base from which I am supposed to get information only.
How to do this using an SQL query? It does not need to be specific to Postgres.
Use case statement to group the animals of same categories together
SELECT CASE
WHEN anm_category LIKE '%dog' THEN 'Dogs'
WHEN anm_category LIKE '%cat' THEN 'cats'
ELSE 'Others'
END AS Animals_category,
Sum(anm_sales) AS total_sales
FROM yourtables
GROUP BY CASE
WHEN anm_category LIKE '%dog' THEN 'Dogs'
WHEN anm_category LIKE '%cat' THEN 'cats'
ELSE 'Others'
END
Also this query should work with most of the databases.
By using PostgreSQL's split_part()
select animal||'s' animal_cat,count(*) total_sales,sum(anm_sales) sales_sum from(
select split_part(anm_cat,'_',2) animal,anm_sales from x
)t
group by animal
sqlfiddle
By creating split_str() in MySQL
select animal||'s' animal_cat,count(*) total_sales,sum(anm_sales) sales_sum from(
select split_str(anm_cat,'_',2) animal,anm_sales from x
)t
group by animal
sqlfiddle
You could group by a substr of anm_catogery:
SELECT SUBSTR(anm_catogery, 3) || 's', COUNT(*)
FROM x
GROUP BY anm_catogery
If you have a constant length of the appendix like in the example:
SELECT CASE right(anm_category, 3) AS animal_type -- 3 last char
, sum(anm_sales) AS total_sales
FROM x
GROUP BY 1;
You don't need a CASE statement at all, but if you use one, make it a "simple" CASE:
Simplify nested case when statement
Use a positional reference instead of repeating a possibly lengthy expression.
If the length varies, but there is always a single underscore like in the example:
SELECT split_part(anm_category, '_', 2) AS animal_type -- word after "_"
, sum(anm_sales) AS total_sales
FROM x
GROUP BY 1;