How to search a string inside a string in Oracle - sql

I have a table A with columns Country ID ,Country. and data is like this
US United States
IN India
JP Japan
NP Nepal
etc .
I have different table B which has a column Country which mostly has free text data . Data is like
Texas United States
India KA
XYS Japan WYS
EverestNepal
XYZ
etc.
What i want is that if country column in Table B has a country matching from any column of country in Table A , it should return Country from Table A.
So for the example i gave
Table B has Texas United States --- there is a match in Table A with 'United States' : It should print United States
Table B has India KA ---- there is a match in Table A with 'India':it should print India
EverestNepal --- there is a match in Table A with 'Nepal': it should print Nepal
Table B has
and so on.
To summarize : If the exact match of country in Table B from anywhere in the string is found in Table A, it should print country from Table A
I dont think Like , IN , Substring will work in such situation

INSTR (line #17) is what you probably need.
SQL> with
2 ta (country_id, country) as
3 (select 'US', 'United States' from dual union all
4 select 'IN', 'India' from dual union all
5 select 'JP', 'Japan' from dual union all
6 select 'NP', 'Nepal' from dual
7 ),
8 tb (country) as
9 (select 'Texas United States' from dual union all
10 select 'India KA' from dual union all
11 select 'XYS Japan WYS' from dual union all
12 select 'EverestNepal' from dual union all
13 select 'XYZ' from dual
14 )
15 select b.country B_country,
16 a.country A_country
17 from ta a right join tb b on instr(b.country, a.country) > 0;
B_COUNTRY A_COUNTRY
------------------- -------------
Texas United States United States
India KA India
XYS Japan WYS Japan
EverestNepal Nepal
XYZ
SQL>

You can use like operator to join between the tables:
SELECT
A.COUNTRY
FROM
TABLE_A A
JOIN TABLE_B B ON ( A.COUNTRY LIKE '%'
|| B.COUNTRY
|| '%' );
Cheers!!

Related

SQL How to access element of a different table?

I have this table [pets]
Animal
prev_store
curr_store
Cat
ABC
DEF
Dog
ABC
GHI
Fish
DEF
XYZ
Snake
XYZ
JKM
I also have this other table [pet_store]
Store
Country
ABC
England
DEF
Denmark
GHI
England
XYZ
Denmark
JKM
Denmark
I want to check for each animal in pets table, whether the prev_store and curr_store is in the same Country, and if so, make a record of the Country.
Country
Occurrences
England
1
Denmark
2
SELECT pet_store.Country, count(pet_store.Country)
FROM pet_store, pets
WHERE pets.prev_store = pet_store.Store
and pets.curr_store = pet_store.Store
GROUP BY pet_store.Country
Unsure about how I would then select the animals's Country in relevance to the prev and curr store.
You will have to use pets_store twice, in two roles, in the query:
WITH
-- your data, don't use in query ..
pets(Animal,prev_store,curr_store) AS (
SELECT 'Cat' ,'ABC','DEF'
UNION ALL SELECT 'Dog' ,'ABC','GHI'
UNION ALL SELECT 'Fish' ,'DEF','XYZ'
UNION ALL SELECT 'Snake','XYZ','JKM'
)
,
pets_store(Store,Country) AS (
SELECT 'ABC','England'
UNION ALL SELECT 'DEF','Denmark'
UNION ALL SELECT 'GHI','England'
UNION ALL SELECT 'XYZ','Denmark'
UNION ALL SELECT 'JKM','Denmark'
)
-- real query starts here ...
SELECT
prev_stores.country AS country
, COUNT(*) AS occurrences
FROM pets
JOIN pets_store prev_stores ON prev_store = prev_stores.store
JOIN pets_store curr_stores ON curr_store = curr_stores.store
WHERE prev_stores.country = curr_stores.country
GROUP BY prev_stores.country;
-- out country | occurrences
-- out ---------+-------------
-- out Denmark | 2
-- out England | 1

Select a value from Table 2 that depends on another value from Table 1 (Oracle SQL)

I'm trying to do some DB during the lockdown and would appreciate some help, since I have been doing this for 5 hours without luck. Got a PDF from a book and sadly, the solutions part isn't readable.
Here are two tables:
**Table 1 named Laptop**
Laptop ID(PK) Name
1 Lenovo
2 Asus
3 Mac
**Table 2 named Buyers**
Buyer ID(PK) Buyer Name Laptop ID(FK) Country
A Jet Li 1 China
B Hermione 1 UK
C Mercato 2 Spain
The activity requests that I create an
"SQL statement that selects all bags names and their buyer name (so 2 columns only), and to show null values as well" because Mac doesn't have a buyer.
I have been trying JOIN and UNION, but no lock.
SELECT Name from Laptop
UNION
SELECT Buyer name from Buyers;
Thank you very much
You need an OUTER JOIN:
SELECT
l.name,
b.buyer_name
FROM
laptop l
LEFT OUTER JOIN buyers b
ON l.laptop_id = b.bag_id;
Demo:
with laptop as(
select 1 laptop_id, 'Lenevo' name from dual union all
select 2 laptop_id, 'Asus' name from dual union all
select 3 laptop_id, 'Mac' name from dual
),
buyers as(
select 'Jet Li' buyer_name, 1 bag_id from dual union all
select 'Hermione' buyer_name, 1 bag_id from dual union all
select 'Mercato' buyer_name, 2 bag_id from dual
)
SELECT
l.name,
b.buyer_name
FROM
laptop l
LEFT OUTER JOIN buyers b
ON l.laptop_id = b.bag_id;
NAME BUYER_NAME
---------- --------------------
Lenevo Jet Li
Lenevo Hermione
Asus Mercato
Mac NULL

Adding a new column that auto increments based on existing field values

Not sure how to do this, but I want to add a new column "Jersey" that will increment by 1 depending on the "Sport" value in both tab_A and tab_B. So if a "Sport" already exists in tab_B, then just grab the max jersey_no and add 1 for the new column. That one is easy.
Now if the "Sport" does not exist in tab_B, then give it a "Jersey" value of 100 for the new column. However, if there is more than one of the same "Sport" in tab_A (but do not exist in tab_B), then it should start with 100 and increment by 1 for the next same Sport, and so on (e.g. see Garcia example below).
I created a sequence "seqnce" but, that really didn't help at all. Is there another way to accomplish this? Thanks in advance!
Tab_A
Name State Sport
Garcia CA Basketball
Garcia AL Basketball
Garcia NY Basketball
McGee CA Swimming
Tontou CA Football
Tontou AL Swimming
Tab_B
Name Sport Jersey_No
Garcia Swimming 100
Garcia Football 100
McGee Swimming 101
Tontou Swimming 101
Tontou Swimming 102
Expected Output
Name State Sport Jersey
Garcia CA Basketball 100
Garcia AL Basketball 101
Garcia NY Basketball 102
McGee CA Swimming 102
Tontou CA Football 100
Tontou AL Swimming 103
My Code
select name, state, sport
,nvl ((select max(b.jersey_no + 1) from tab_b b
where b.sport = a.sport
and b.name = a.name),
(case
when not exists (select 1 from tab_b b
where b.sport = a.sport
and b.name = a.name
having count(a.sport) > 1)
then seqnce.nextval
else '100'
end )
) Jersey
from tab_a
If it's only select result then using row_number(). If you need update column in table, then write trigger
Example this:
WITH taba AS
(SELECT 'Garcia' Name, 'CA' State, 'Basketball' Sport from dual
UNION ALL
SELECT 'Garcia' Name, 'AL' State, 'Basketball' Sport from dual
UNION ALL
SELECT 'Garcia' Name, 'NY' State, 'Basketball' Sport from dual
UNION ALL
SELECT 'McGee' Name, 'CA' State, 'Swimming' Sport from dual
UNION ALL
SELECT 'Tontou' Name, 'CA' State, 'Football' Sport from dual
UNION ALL
SELECT 'Tontou' Name, 'AL' State, 'Swimming' Sport from dual),
tabb AS
(SELECT 'Garcia' Name, 'Swimming' Sport, 100 Jersey from dual
UNION ALL
SELECT 'Garcia' Name, 'Football', 100 from dual
UNION ALL
SELECT 'McGee' Name, 'Swimming', 101 from dual
UNION ALL
SELECT 'Tontou' Name, 'Swimming', 101 from dual
UNION ALL
SELECT 'Tontou' Name, 'Swimming', 102 from dual)
SELECT taba.Name,
taba.State ,
taba.Sport,
row_number() over(partition by taba.Name, taba.Sport ORDER BY taba.State)
+ nvl((SELECT MAX(tabb.Jersey)
FROM tabb
WHERE taba.name = tabb.name
AND taba.sport = tabb.sport), 99)
FROM taba
result:
Garcia AL Basketball 100
Garcia CA Basketball 101
Garcia NY Basketball 102
McGee CA Swimming 102
Tontou CA Football 100
Tontou AL Swimming 103

Ordering Query for Country & City data for the scenario given

My input data is below :
**Country city**
Australia Sydney
Australia melbourne
India Delhi
India Chennai
India Bangalore
Afghanistan Kabul
Output expected is:
Afghanistan
Kabul
Australia
melbourne
syndey
India
Bangalore
Chennai
Delhi
The data in both columns should be arranged alphabetically(both city level and country level) and result should be single column with above values. The country should be alphabetically ordered and the corresponding cities should go below them which should also be alphabetically ordered.
How can this be done without using an intermediate table in a single query?
You need a UNION ALL query to get one row per country and one row per city in your result:
select coalesce(city, country) as location
from
(
select distinct country, null as city from mytable
union all
select country, city from mytable
)
order by country, city nulls first;
This has a single table scan and also does not need to use UNION to get distinct results:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE cities ( Country, city ) AS
SELECT 'Australia', 'Sydney' FROM DUAL UNION ALL
SELECT 'Australia', 'melbourne' FROM DUAL UNION ALL
SELECT 'India', 'Delhi' FROM DUAL UNION ALL
SELECT 'India', 'Chennai' FROM DUAL UNION ALL
SELECT 'India', 'Bangalore' FROM DUAL UNION ALL
SELECT 'Afghanistan', 'Kabul' FROM DUAL;
Query 1:
SELECT value
FROM (
SELECT c.*,
country AS ctry,
ROW_NUMBER() OVER ( PARTITION BY Country ORDER BY city ) AS rn
FROM cities c
)
UNPIVOT( value FOR key IN ( Country AS 1, City AS 2 ) )
WHERE rn = 1 OR key = 2
ORDER BY ctry, rn, key
Results:
| VALUE |
|-------------|
| Afghanistan |
| Kabul |
| Australia |
| Sydney |
| melbourne |
| India |
| Bangalore |
| Chennai |
| Delhi |

Split data over multiple columns into rows (in SQL or SAS)

I have data in the following form:
Country City1 City2 City3 AverageTemperature
UK London Glasgow Manchester 15
Italy Rome Naples Venice 25
Germany Munich Berlin 20
USA New York 25
With either SQL or a SAS data step, I would like to get the data in this form:
Country City AverageTemperature
UK London 15
UK Glasgow 15
UK Manchester 15
Italy Rome 25
Italy Naples 25
Italy Venice 25
Germany Munich 20
Germany Berlin 20
USA New York 25
So that I have the data across individual rows. I have thought about doing this by looping over the three city columns where the city is not blank, but I'm not sure how to confidently do this - is it easily done with either SQL or SAS? Just a pointer would be greatly appreciated.
SELECT COUNTRY, City1, AverageTemperature FROM Table_Name
UNION ALL
SELECT COUNTRY, City2, AverageTemperature FROM Table_Name
UNION ALL
SELECT COUNTRY, City3, AverageTemperature FROM Table_Name
To get rows where City column is not null you can do something like this
SELECT COUNTRY, City1, AverageTemperature FROM Table_Name
WHERE City1 IS NOT NULL
UNION ALL
SELECT COUNTRY, City2, AverageTemperature FROM Table_Name
WHERE City2 IS NOT NULL
UNION ALL
SELECT COUNTRY, City3, AverageTemperature FROM Table_Name
WHERE City3 IS NOT NULL
Simple in a SAS Data Step
data out;
set in;
array cities[3] city1-city3;
format city $12.;
do i=1 to 3;
if compress(cities[i]) ^= "" then do;
city = cities[i];
output;
end;
end;
keep country city AverageTemperature;
run;
You can unpivot this using "relatively" standard SQL. Here is an approach that only requires scanning the data once:
select country, city, averagetemperatur
from (select t.country,
(case when n = 1 then t.city1
when n = 2 then t.city2
when n = 3 then t.city3
end) as city,
t.averagetemperature
from t cross join
(select 1 as n union all select 2 union all select 3) n
) t
where city is not null;
The exact syntax for creating the table with three rows (n) can vary depending on the database.
A macro loop should do the job:
%MACRO Cities ;
%DO N=1 %TO 3 ;
proc sql ;
create table Cities_&N as
select Country, City&N as City, AverageTemperature
from your_table_name_here
where City&N is not null ;
quit ;
%END ;
data Cities ;
set Cities_: ;
run ;
%MEND ;
%Cities ;