Select number of comma delimited list items - sql

I have a column that has comma seperated values and I need to select all rows that have 13 commas. They seperate numbers so I don't need to worry about any strings that contain commas. How would I do this?

alternative to like (I do not like the like, and the above will fail if contains 14 commas or more)
select * from table
where length(replace(your_column, ',', ''))=length(your_column)-13;
for better utilize the index, you should seek to normalize your table

If you're using PostgreSQL, you could also use regular expressions.
However, a better question might be why you have a single column with comma-separated values instead of multiple columns.

If you count a string with 14 commas as having 13 commas, then this will work:
SELECT * FROM table WHERE column LIKE '%,%,%,%,%,%,%,%,%,%,%,%,%,%'
% matches any string (including zero length).

In PostgreSQL you can do:
select col from table where length(regexp_replace(col, '[^,]', '', 'g')) = 13;

Related

check if column contains one of many values

i have an array of strings and a column which may contain one or more of those strings(seperated by space) i want to get all rows where this column contains one of the strings. Since the values all have 3 letters and therefore can't contain each other, i know i could just write
SELECT * FROM table WHERE
column LIKE '%val1%' OR
column LIKE '%val2%' OR
column LIKE '%val3%' OR
column LIKE '%val4%'
But i'm wondering if there isn't an easier statement, like column IN ('val1', 'val2', 'val3', 'val4') (This one seems only to work when the entry is equal to one of the values, but not if it just contains them)
Try reading this Is there a combination of "LIKE" and "IN" in SQL? and Combining "LIKE" and "IN" for SQL Server , this will solve you question.
Something like this from the first link.
SQL Server:
WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')
Ist oracle you could use regular expressions
select *
from table
where regexp_like (column,'val(1|2|3|4)')

Finding numeric values in varchar field

sorry if this is a duplicate, I wasn't able to find what I was looking for in the answered questions.
I'm looking to query for only records with a field formatted like this numbers (0-9), hyphen (-), number (0-9), hyphen (-), numbers (0-9). This is what I have tried:
SELECT *
FROM TABLE_1
WHERE LTRIM(RTRIM(LOC_NAME)) LIKE '[0-9]-[0-9]-[0-9]'
The result set I'm looking for would be 123456-123-1234.
I thought at first they may have spaces so I trimmed the field but still no results are showing with the ABOVE query. The BELOW query returns them, but with other results:
SELECT *
FROM TABLE_1
WHERE LOC_NAME LIKE '%[0-9]-[0-9]%'
But I would get results like 1-2-3 Place...
I think this does what you want:
SELECT *
FROM TABLE_1
WHERE LTRIM(RTRIM(LOC_NAME)) NOT LIKE '%[^-0-9]%'
This checks that the field has no non-hyphens or non-digits.
If you specifically want two hyphens, separated by digits, then:
WHERE LTRIM(RTRIM(LOC_NAME)) NOT LIKE '%[^-0-9]%' AND
LTRIM(RTRIM(LOC_NAME)) LIKE '[0-9]%-[0-9]%-[0-9]%' AND
LTRIM(RTRIM(LOC_NAME)) NOT LIKE '%-%-%-%'
The second pattern requires at least two hyphens and a digit in all three parts of the name. The third forbids three hyphens.
I would do this way
select *
from table_1
where isnumeric(replace(LOC_NAME, '-','')) = 1;
Update (2018-Jun-12)
After reading the comments of #EzLo, I realized that the OP may just need two hyphens (no more, no less), so I am updating my answer with the following demo code
create table #t (LOC_NAME varchar(100));
go
insert into #t (loc_name)
values ('a12-b12-123'), ('123456-123-11'), ('123-123-123-123')
go
select *
from #t --table_1
where isnumeric(replace(LOC_NAME, '-','')) = 1
and len(loc_name)-len(replace(LOC_NAME, '-',''))=2
The result is:

How to spread the values from a column in Hive?

One field of table is made up of many values seperated by comma,
for example, a record of this field is:
598423,4803510,599121,98181856,1666529,106317962,4061964,7828860,598752,728067,599809,8799578,1666528,3253720,601990,601235
I want to spread the values in every record of this field in Hive.
Which function or method I can use to realize this?
Thanks.
I'm not entirely sure what you mean by "spread".
If you want an output table that has a value in every row like:
598423
4803510
599121
Then you could use explode(split(data,',')
Otherwise, if each input row has exactly 16 numbers and you want each of the numbers to reside in a different column, you have two options:
Define the comma as a delimiter for the input table ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
Split a single column into 16 columns using the split UDF: SELECT split(data,',')[0] as col1, split(data,',')[1] as col2, ...

Select if comma separated string contains a value

I have table
raw TABLE
=========
id class_ids
------------------------
1 1234,12334,12341,1228
2 12281,12341,12283
3 1234,34221,31233,43434,1123
How to define regex to select raws if class_ids contains special id.
If we select raws with '1234' in class_ids result list should not contain raws with '12341' in class_ids.
IDs in column class_ids separated with ,
SELECT FROM raw re WHERE re.class_ids LIKE (regex)
You shouldn't be storing comma separated values in a single column.
However, this is better done using string_to_array() in Postgres instead of a regex:
SELECT *
FROM raw
WHERE '1234'= any(string_to_array(class_ids, ','));
If you really want to de-normalize your data, it's better to store those numbers in a proper integer array, instead of comma separated list of strings
A simple way uses like:
where ',' || re.class_ids || ',' like '%,1234,%'
However, this is not the real issue. You should not be storing lists of ids in a string. The SQLish way of storing them would have a table with one row per id and one row per class_id. This is called a junction table.
Even if you don't use a separate table, you should at least use Postgres's built-in mechanisms, such as an array. However, a separate table is much the preferred method, because you can explicitly declare foreign key relationships.
If you really want to do this with regular expressions, you can use the ~ operator:
SELECT FROM raw re WHERE re.class_ids ~ '^(^|,)1234(,|$)$';
But I prefer a_horse_with_no_name's answer that uses arrays.

Oracle SQL - Joining list of values to a field with those values concatenated

The title is a bit confusing, so I'll explain with an example what I'm trying to do.
I have a field called "modifier". This is a field with concatenated values for each individual. For example, the value in one row could be:
*26,50,4 *
and the value in the next row
*4 *
And the table (Table A) would look something like this:
Key Modifier
1 *26,50,4 *
2 *4 *
3 *1,2,3,4 *
The asterisks are always going to be in the same position (here, 1 and 26) with an uncertain number of numbers in between, separated by commas.
What I'd like to do is "join" this "modifier" field to another table (Table B) with a list of possible values for that modifier. e.g., that table could look like this:
ID MOD
1 26
2 3
3 50
4 78
If a value in A.modifier appears in B.mod, I want to keep that row in Table A. Otherwise, leave it out. (I use the term "join" loosely because I'm not sure that's what I need here.)
Is this possible? How would I do it?
Thanks in advance!
edit 1: I realize I can use regular expressions and do a bunch of or statements that search for the comma-separated values in the MOD list, but is there a better way?
One way to do it is using TRIM, string concatenations and LIKE.
SELECT *
FROM tableA a
WHERE EXISTS(
SELECT 1 FROM tableB b
WHERE
','|| trim( trim( BOTH '*' FROM a.Modifier )) ||','
LIKE '%,'|| b.mod || ',%'
);
Demo --> http://www.sqlfiddle.com/#!4/1caa8/10
This query migh be still slow for huge tables (it always performs full scans of tables or indexes), however it should be faster than using regular expressions or parsing comma separated lists into individual values.