SQL, joining the same table - sql

I have a table with the columns code and document. The column code may have alphanumeric values (only letters) and/or numeric values (only digits). In the model, every numeric code has an alphanumeric equivalent code. The records below represent an example of this situation (in the form (document,code);(document,code):
(12345678900,ABC);(12345678900,999)
But, a alphanumeric code may not always have a equivalent numeric code, so the example below represents a situation where we have 3 different records
(12345678900,ABC);(12345678900,999);(00987654321,XYZ);(11111111111,DEF)
With this in mind, what I want to do is the following: what I'll use to search records is always alphanumeric codes, and when I have an equivalent numeric, I want as result the numeric one, but when the alpha doesn't have the numeric equivalent, I want the alphanumeric code.
For instance, if I execute the following selects, I would get the results below:
SELECT code FROM table WHERE code = 'ABC' -> Result: 999
SELECT code FROM table WHERE code = 'DEF' -> Result: DEF
SELECT code FROM table WHERE code = 'XXX' -> Result: (blank)
I appreciate if anybody could help me please.
Regards,
AMR

Try this
SELECT
f1.doc
, COALESCE(f2.code, f1.code) code
FROM foo f1
LEFT JOIN(
SELECT doc, code
FROM foo
WHERE code <> #code
) f2 ON f2.doc = f1.doc
WHERE f1.code = #code
demo

Related

Selecting substrings from different points in strings depending on another column entry SQL

I have 2 columns that look a little like this:
Column A
Column B
Column C
ABC
{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}
1.0
DEF
{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}
24.0
I need a select statement to create column C - the numerical digits in column B that correspond to the letters in Column A. I have got as far as finding the starting point of the numbers I want to take out. But as they have different character lengths I can't count a length, I want to extract the characters from the calculated starting point( below) up to the next comma.
STRPOS(Column B, Column A) +5 Gives me the correct character for the starting point of a SUBSTRING query, from here I am lost. Any help much appreciated.
NB, I am using google Big Query, it doesn't recognise CHARINDEX.
You can use a regular expression as well.
WITH sample_table AS (
SELECT 'ABC' ColumnA, '{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}' ColumnB UNION ALL
SELECT 'DEF', '{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}' UNION ALL
SELECT 'XYZ', '{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}'
)
SELECT *,
REGEXP_EXTRACT(ColumnB, FORMAT('"%s":([0-9.]+)', ColumnA)) ColumnC
FROM sample_table;
Query results
[Updated]
Regarding #Bihag Kashikar's suggestion: sinceColumnB is an invalid json, it will not be properly parsed within js udf like below. If it's a valid json, js udf with json key can be an alternative of a regular expression. I think.
CREATE TEMP FUNCTION custom_json_extract(json STRING, key STRING)
RETURNS STRING
LANGUAGE js AS """
try {
obj = JSON.parse(json);
}
catch {
return null;
}
return obj[key];
""";
SELECT custom_json_extract('{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}', 'ABC') invalid_json,
custom_json_extract('{"ABC":1.0,"DEF":24.0,"XYZ":10.50}', 'ABC') valid_json;
Query results
take a look at this post too, this shows using js udf and with split options
Error when trying to have a variable pathsname: JSONPath must be a string literal or query parameter

How to do a regex compare of string values in 2 columns in big query

So let’s say I have 2 columns, both containing string values,
ColA , ResultCol
I want to check if In a row, the string in ColA is a substring of string in ResultCol
I know about ‘WHERE REGEXP_CONTAINS(col, regex)’ , but how do I do this comparison with string in another column?
Please let me know if I missed explaining any criteria of the question
Thanks!
For your requirement, you can use like operator in BigQuery which will compare the strings of two columns.I have created a sample table Product and ran the below code:
Code
SELECT * from `project.dataset.Product` where product like concat('%',country,'%')
Sample Table
Output

Oracle ERROR-01722 not showing up consistently

There seems to be inconsistencies with how ERROR-01722 error worked, for those who don't know the issue is due to an invalid number and to fix it you'll need to wrap the number to char.
But when filtering VARCHAR2 it is stated that Oracle will convert the data of the column being filtered based on the value given to it. (see: https://stackoverflow.com/a/10422418/5337433)
Now that this is explained for some reason, the error is inconsistent. As an example I have this query:
In this example filter1 is varchar2
select *
from table
where filter1 = 12345
and filter2 = ''
and filter3 = '';
When this statement run there were no issues, but when you run it like this:
select *
from table
where filter1 = 12345
and filter2 = '';
it errors out to ERROR-01722, im not sure why it is acting this way, and how to fix it.
When you compare a varchar column to a number, Oracle will try to convert the column's content to a number, not the other way round (because 123 could be stored as '0123' or '00123')
In general you should always use constant values that match the data type of the column you compare them with. So it should be:
where filter1 = '12345'
However if you are storing numbers in that column, you should not define it as varchar - it should be converted to a proper number column.
The reason the error doesn't show up "consistently" is that you seem to have some values that can be converted to a number and some can't. It depends on other conditions in the query if the those values are included or not.
Additionally: empty strings are converted to NULL in Oracle. So the condition filter2 = '' will never be true. You will have to use filter2 is null if you want to check for an "empty" column.

Can I combine like and equal to get data?

I have data like this
1234500010
1234500020
1234500021
12345600010
12345600011
123456700010
123456700020
123456710010
The pattern is
1-data(varian 3-7 digit number) + 2-data(any 3 digit number) + 3-data (any 2 digit number)
I want to create SQL to get 1-data only.
For example I want to get data 12345
I want the result only
1234500010
1234500020
1234500021
If I using "like",
select *
FROM data
where ID like '12345%' `
I will get all the data with 12345, 123456 and 1234567
If I using equal, I will only get one specific data.
Can I combine like and equal together to get result like what I want?
select * FROM data where data = '12345 + any 2-data(3 digit) + any 3-data(2 digit)'
Anyone can help?
Addition : Sorry if I didn't mention the data type and make some miss communication. The data type is in char. #Gordon answers and the others not wrong. It works for number and varchar. but not works for char type. Here I post some pic for char data type. Oracle specification for char data type is a fixed lenght. So if I input less than lenght the remain of it will be change into a space.
Thank you very much. Hope someone can help for this
Since your datatype is CHAR, Gordon's answer is not working for you. CHAR adds trailing spaces for the strings less than maximum limit. You could use TRIM to fix this as shown. But, you should preferably store numbers in the NUMBER type and not CHAR or VARCHAR2, which will create other problems sooner or later.
select *
from data
where trim(ID) like '12345_____';
I think you want:
select *
from data
where ID like '12345_____' -- exactly 5 _
Here is a rextester demonstrating the answer.
You really can't combine equality and LIKE. But you can use a regular expression to do this kind of searching, with the REGEXP_LIKE function:
SELECT *
FROM DATA
WHERE REGEXP_LIKE(ID, '^12345[0-9]{3}[0-9]{2}');
But if I understand correctly, for your 1-data you really want a 3 to 7 digit number:
SELECT *
FROM DATA
WHERE REGEXP_LIKE(ID, '^[0-9]{3,7}[0-9]{3}[0-9]{2}');
Oracle regular expression docs here
SQLFiddle here
Best of luck.
I think this gives you the solution you want,
create table data(ID number(15));
insert into data values(1234500010);
insert into data values(1234500020);
insert into data values(1234500021);
insert into data values(12345600010);
insert into data values(12345600011);
insert into data values(123456700010);
insert into data values(123456700020);
insert into data values(123456710010);
select * from data where ID like '12345_____'
// After 5_ underscore are exactly 5 , any 3 digits from 2-data(3 underscores) and 2 digits from 3-data(2 underscores)
You'll be getting(OUTPUT) :
ID
1234500010
1234500020
1234500021
3 rows returned in 0.00 seconds

Hard request SQL Server 2008

I have a pretty hard request to do in SQL Server 2008, but I'm not able to do the whole...
I have two kind of records :
16HENFC******** (8 numbers after more 'FC')
16HEN******* (7 numbers after more 'EN')
I have to select the * (which are in fact numbers), and add a 0 at the beginning of the second form of record to just have 8 long selected values.
Then I have to insert the result in a empty table.
I think I did the first part which is :
SUBSTRING(SELECT mycolumn1 FROM mytable1 WHERE mycolumn1 LIKE '16HENFC%', 5, 8) ;
In summary,
I have those records in my column :
'16HENFC071052'
'16HEN5130026'
I want to select them and transform them to insert those ones in an other column :
'05130026'
'FC071052'
[EDIT]=>
CREATE TABLE nom_de_la_table
(
colonne1 VARCHAR(250),
colonne2 VARCHAR(250)
)
INSERT INTO nom_de_la_table (colonne1)
VALUES
('16HEN5138745'),
('16HENFC071052v2'),
('16HENFC78942878'),
('16HEN4830026'),
('16HEN7815934'),
('16HENFC74859422'),
('16HEN9687326'),
('16HENFC74889639'),
('16HEN9798556');
[etc...]
So two different types of records, and I want to insert the result of what you did first with just two records in an other column but for the 956 records of my table. And this is the result with the two examples :
'05130026'
'FC071052'
Left-Filling a string is a relatively easy request. Here's an example:
select right(replicate('0',8) + right(test,len(test)-len('16HEN')),8)
from (
select '16HENFC071052' as test
union all
select '16HEN5130026' as test
) z
Use replicate to left-fill your string with the amount of digits you wish to end up with. Append your desired string, in this case, slice your prefix off by taking the right X characters where X = len(target) - len(prefix). Finally, take the right characters of the whole string equal to your desired length.