I have a list of comma separated values in a single field and need to find all rows which meet a certain criteria. The code I am using is:
select * from table where column_name in
(
select regexp_substr('A+','A-','aabn','[^,]+', 1,level) from table
connect by regexp_substr('A+','A-','aabn', '[^,]+', 1,level) is not null
);
so I want to find all the rows which contain A+, A- and aabn
Why not just use a single regular expression?
where regexp_like(column_name, '(^|,)(A[+]|A[-]|aabn)($|,)')
Here is a DB<>fiddle.
Also, as powerful as regular expressions are, you should not be storing multiple values in a single string. Oracle has many other options for storing multiple values, including the traditional association/junction table.
You don't need regular expressions, just use LIKE to check that the value you require is a sub-string of the column (both surrounded by delimiter characters):
If you want all 3 in the list then use AND:
SELECT *
FROM table_name
WHERE ',' || column_name || ',' LIKE '%,A+,%'
AND ',' || column_name || ',' LIKE '%,A-,%'
AND ',' || column_name || ',' LIKE '%,aabn,%'
If you want any 1 in the list then use OR:
SELECT *
FROM table_name
WHERE ',' || column_name || ',' LIKE '%,A+,%'
OR ',' || column_name || ',' LIKE '%,A-,%'
OR ',' || column_name || ',' LIKE '%,aabn,%'
Related
I need to pull a query from multiple columns from a table. Some rows will have data in one column, others will have two, three, and even four.
I tried to use this construct:
SELECT person_uid,('(' || major || NVL((',' ||second_major), '') || NVL((',' ||third_major), '') || NVL(',' ||fourth_major, '') || ')' ) AS MAJORS FROM academic_study
But the result would be like this:
6231 (BUMG,BUMK,,)
19091 (TDST,TDPG,,)
I need the parentheses, but not the trailing commas.
I could potentially strip out the extra commas in post processing, but I would prefer to do it in the SQL. I am using ORACLE.
You should fix your data model! Storing multiple columns with parallel data is awkward.
One method is:
select person_uid,
( '(' || major ||
(case when second_major is not null then ',' || second_major end) ||
(case when third_major is not null then ',' || third_major end) ||
(case when fourth_major is not null then ',' || fourth_major end) ||
')'
)
I need to create a column that has all the values from the previous columns combined and separated using commas ', '
I can't use listagg since I'm trying to combine multiple columns instead of rows.
below is an example of how the result column should look like, thanks.
Use string concatenation:
select trim(leading ',' from
(case when column1 is not null then ',' || column1 end) ||
(case when column2 is not null then ',' || column2 end) ||
(case when column3 is not null then ',' || column3 end)
)
This is also using a string concatenation but slightly different
SELECT
SUBSTR(
REPLACE(
', ' || NVL(column1,'!!') || ', ' || NVL(column2,'!!') || ', ' || NVL(column3,'!!')
,', !!','')
,3,100)
C.ADDRESS1 || ',' || C.ADDRESS2 || ',' || C.ADDRESS3
pa.address_line_1,
pa.address_line_2,
pa.address_line_3 from per_addresses_f pa ;
how to join three column as single address column with oracle SQL concatenate
How to write query for joining 3 columns as single column?
You can write the concatenation as you've written it, but you have to make sure that all the components are strings. If some of them isn't, put it in TO_CHAR function. It's also good to put an alias to your result of concatenated columns:
SELECT C.ADDRESS1 || ',' || C.ADDRESS2 || ',' || C.ADDRESS3 as concatenated_adress
FROM your_table c
EDIT : After question was edited with concrete columns that are used, table name and with desired alias stated in question columns:
SELECT pa.address_line_1 || ',' || pa.address_line_2 || ',' || pa.address_line_3
as "Emergency Address"
FROM per_addresses_f pa
You can do this:
CONCAT(C.ADDRESS1, ',', C.ADDRESS2, ',', C.ADDRESS3) AS newColumnName
Try this :
SELECT firstname ||' '|| lastname AS employee_name FROM employee;
You can also try nested CONCAT assuming all address_line fields have char datatype:
SELECT CONCAT(CONCAT(CONCAT(pa.address_line_1,','),CONCAT(pa.address_line_2,',')),pa.address_line_3) AS address FROM per_addresses_f pa
But clearly pipe operator as suggested by #Goran Kutlaca is much simpler.
There are multiple ways to Concate the column in BIP.
1.
SELECT pa.address_line_1 || ',' || pa.address_line_2 || ',' ||
pa.address_line_3
as "Emergency Address" FROM per_addresses_f pa
2.
SELECT
CONCAT(CONCAT(CONCAT(pa.address_line_1,','),CONCAT(pa.address_line_2,',')),pa.address_line_3)
AS address FROM per_addresses_f pa
3.
select
CONCAT(pa.address_line_1,',',pa.address_line_2,',',pa.address_line_3)
as address FROM per_addresses_f pa
I need a query to count the total number of non-null values for each column in a table. Since my table has hundreds of columns I'm looking for a solution that only requires me to input the table name.
Perhaps using the result of:
select COLUMN_NAME from ALL_TAB_COLUMNS where TABLE_NAME='ORDERS';
to get the column names and then a subquery to put counts against each column name? The additional complication is that I only have read-only access to the DB so I can't create any temp tables.
Slightly out of my league with this one so any help is appreciated.
Construct the query in SQL or using a spreadsheet. Then run the query.
For instance, assuming that your column names are simple and don't have special characters:
select replace('select ''[col]'', count([col]) from orders union all ',
'[col]', COLUMN_NAME
) as sql
from ALL_TAB_COLUMNS
where TABLE_NAME = 'ORDERS';
(Of course, this can be adapted for more complex column names, but I'm trying to show the idea.)
Then copy the code, remove the final union all and run it.
You can put this in one string if there are not too many columns:
select listagg(replace('select ''[col]'', count([col]) from orders',
'[col]', COLUMN_NAME
), ' union all '
) within group (order by column_name) as sql
from ALL_TAB_COLUMNS
where TABLE_NAME = 'ORDERS';
You can also use execute immediate using the same query, but that seems like overkill.
If you're happy with the results row-ar rather than column-ar:
SELECT 'SELECT ''dummy'', 0 FROM DUAL' FROM DUAL
UNION ALL
SELECT
' UNION ALL SELECT ''' ||
column_name ||
''', COUNT(' ||
column_name ||
') FROM ' ||
TABLE_NAME
FROM
all_tab_columns
WHERE
table_name = 'ORDERS'
This is an "SQL that writes an SQL" that you can then copy and run to get your answers. Should make a resultset that looks like:
SELECT 'dummy', 0 FROM dual
UNION ALL SELECT 'col1', COUNT(col1) FROM ORDERS
UNION ALL SELECT 'col2', COUNT(col2) FROM ORDERS
...
If you want your results column-ar:
SELECT 'SELECT '
UNION ALL
SELECT
'COUNT(' ||
column_name ||
') as count_' ||
column_name ||
', ' ||
TABLE_NAME
FROM
all_tab_columns
WHERE
table_name = 'ORDERS'
UNION ALL
SELECT 'null as dummy_column FROM ORDERS'
Should make a resultset that looks like:
SELECT
COUNT(col1) as count_col1,
COUNT(col2) as count_col2,
...
null as dummycoll FROM orders
Caveat: I don't have oracle installed anywhere I can test these, it's written from memory and may need some debugging
This will generate the SQL to get the counts in columns and will handle case sensitive column names and column names with non-alpha-numeric characters:
SELECT 'SELECT '
|| LISTAGG(
'COUNT("' || column_name || '") AS "' || column_name || '"',
', '
) WITHIN GROUP ( ORDER BY column_id )
|| ' FROM "' || table_name || '"' AS sql
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = 'ORDERS'
GROUP BY TABLE_NAME;
or, if you have a large number of columns that is generating a string longer than 4000 characters you can use a custom aggregation function to aggregate VARCHAR2s into a CLOB and then do:
SELECT 'SELECT '
|| CLOBAgg( 'COUNT("' || column_name || '") AS "' || column_name || '"' )
|| ' FROM "' || table_name || '"' AS sql
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = 'ORDERS'
GROUP BY TABLE_NAME;
In Oracle 19 (I used similar code in Ora 12, maybe that works too), this works without generating another select to execute:
select * from
(
select table_name, column_name,
to_number( extractvalue( xmltype(dbms_xmlgen.getxml('select count(to_char(substr('||column_name||',1,1))) c from '||table_name)) ,'/ROWSET/ROW/C')) count
from all_tab_columns where owner = user
)
--where table_name = 'MY_TABLE'
;
It will create XML with count, from which it extracts the current count. The substr and to_char functions here are used to extract first character, so it will works with CLOB columns also
I have a query which uses IN clause and it is not working for below case:
Select *
from table1
where
Rollno || '/' || UserId IN ('1/001,2/002')
It is not working because you haven't wrapped each value in single quotes ' :
SELECT *
FROM table1
WHERE Rollno || '/' || UserId IN ('1/001','2/002')
Notulysses has the right syntax for in. But, if you have to deal with a string, you can rephrase this as like:
where ',' || Rollno || '/' || UserId || ',' like '%,' || '1/001,2/002' || ',%'
like is a better approach. Sometimes in the real world, you might have to deal with comma-delimited strings.