SQL JOINING ISSUE - sql

I have two different tables but both table may or may not have same records. i need to join these tables and get all the different records for both the tables
for example
CREATE TABLE sql_test_a
(
ID VARCHAR2(4000 BYTE),
FIRST_NAME VARCHAR2(200 BYTE),
LAST_NAME VARCHAR2(200 BYTE)
);
CREATE TABLE sql_test_b
(
ID VARCHAR2(4000 BYTE),
FIRST_NAME VARCHAR2(200 BYTE),
LAST_NAME VARCHAR2(200 BYTE)
);
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('1', 'John', 'Snow');
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('2', 'Mike', 'Tyson');
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('3', 'Bill', 'Keaton');
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('4', 'Greg', 'Mercury');
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('5', 'Steve', 'Jobs');
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('6', 'Stsdsdve', 'Josdsbs');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('1', 'John', 'Snow');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('2', 'Mike', 'Tyson');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('3', 'Bill', 'Keaton');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('4', 'Greg', 'Mercury');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('5', 'Steve', 'Jobs');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('7', 'Johhny', 'Depp');
INSERT INTO sql_test_b (ID, FIRST_NAME, LAST_NAME) VALUES ('8', 'Johhnaaaay', 'Deaaap');
these are the tables and the records in the tables
and the excepted output should be
ID FIRST_NAME LAST_NAME
1 John Snow
2 Mike Tyson
3 Bill Keaton
4 Greg Mercury
5 Steve Jobs
6 Stsdsdve Josdsbs
7 Johhny Depp
8 Johhnaaaay Deaaap
i tried different join like left outer join, full outer join etc
SELECT a.ID,a.FIRST_NAME,a.LAST_NAME
FROM sql_test_a a left outer join sql_test_b b on a.ID=b.ID
and a.FIRST_NAME=b.FIRST_NAME
and a.LAST_NAME=b.LAST_NAME
this query wont give the exact output
please help

The UNION operator returns unique rows of combined queries. So, just use
SELECT * FROM sql_test_a UNION SELECT * FROM sql_test_b
To filter the result using WHERE clause you could use subquery. For example
SELECT *
FROM (SELECT * FROM sql_test_a UNION SELECT * FROM sql_test_b)
WHERE ID > 3
See also live fiddle.

If you use a union you can get the list you need (note that union all could give you duplicate rows depending on your data):
select a.id as id, a.first_name as first_name, a.last_name as last_name
from sql_test_a a
union
select b.id as id, b.first_name as first_name, b.last_name as last_name
from sql_test_b b
Using a join is discouraged in this case since it will give you a table with more than three columns, joined on (at least) one of them.
EDIT
You mention you're using oracle. To filter this, you can do several things, among which, one is wrap the query in a temporary table
with tmp as (
select a.id as id, a.first_name as first_name, a.last_name as last_name
from sql_test_a a
union
select b.id as id, b.first_name as first_name, b.last_name as last_name
from sql_test_b b
)
select tmp.id, tmp.first_name, tmp.last_name
from tmp
where
tmp.first_name like '%whatever%';

Try this Please
( SELECT * FROM sql_test_1
) UNION ALL( SELECT * FROM sql_test_b
EXCEPT
SELECT * FROM sql_test_1 )

( SELECT * FROM sql_test_a
MINUS
SELECT * FROM sql_test_b) UNION ALL( SELECT * FROM sql_test_b
MINUS
SELECT * FROM sql_test_a )

Related

Inserting data into table with select

i`m trying to do something.... I have to insert some data in to a table but..... So here is where I end up...
INSERT into HR.my_employees
(ID,LAST_NAME,FIRST_NAME,userid,SALARY)
SELECT
3 AS ID,
'Biri' AS LAST_NAME,
'Ben' AS FIRST_NAME,
substr(FIRST_NAME,1,1)||''||substr(LAST_NAME,1,7) AS userid,
1100 AS salary
FROM dual
UNION
SELECT
4 AS ID,
'Newman' AS LAST_NAME,
'Chad' AS FIRST_NAME,
substr(FIRST_NAME,1,1)||''||substr(LAST_NAME,1,7) AS userid,
750 AS salary
FROM dual;
any suggestion...
You cannot refer to an alias in the SELECT or WHERE clauses of a sub-query where it is defined. Generate the data in a sub-query (or a sub-query factoring clause) and then refer to it in an outer query:
INSERT into HR.my_employees(ID,LAST_NAME,FIRST_NAME,userid,SALARY)
WITH data (id, last_name, first_name, salary) AS (
SELECT 3, 'Biri', 'Ben', 1100 FROM DUAL UNION ALL
SELECT 4, 'Newman', 'Chad', 750 FROM DUAL
)
SELECT id,
last_name,
first_name,
SUBSTR(first_name,1,1) || SUBSTR(last_name,1,7),
salary
FROM data;
or:
INSERT into HR.my_employees(ID,LAST_NAME,FIRST_NAME,userid,SALARY)
SELECT id,
last_name,
first_name,
SUBSTR(first_name,1,1) || SUBSTR(last_name,1,7),
salary
FROM (
SELECT 3 AS id, 'Biri' AS last_name, 'Ben' AS first_name, 1100 AS salary FROM DUAL
UNION ALL
SELECT 4, 'Newman', 'Chad', 750 FROM DUAL
);
fiddle
Why do you want to use select statements? - Based on the values you provide it seems like you want to insert hardcoded values. Or does the dual table contain data you want to insert into HR.my_employees?
If you want to just insert values into the table, but not from an existing one, you can use the following structure:
INSERT INTO table_name (column1, column2, column3, ..., columnXX)
VALUES (value1, value2, value3, ..., valueXX);

SQL UNION query with order by giving syntax error on "("

I'm trying to select 2 oldest females and 2 oldest males using 1 query. The union keeps giving me a syntax error near "(". Both queries work independantly but after union I get error.
-- create a table
CREATE TABLE students (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
gender TEXT NOT NULL,
age INTEGER NOT NULL
);
-- insert some values
INSERT INTO students VALUES (1, 'Ryan', 'M', 23);
INSERT INTO students VALUES (2, 'Joanna', 'F', 22);
INSERT INTO students VALUES (3, 'Alex', 'F', 25);
INSERT INTO students VALUES (4, 'Ted', 'M', 21);
INSERT INTO students VALUES (5, 'June', 'F', 26);
INSERT INTO students VALUES (6, 'Rose', 'F', 24);
INSERT INTO students VALUES (7, 'Jack', 'M', 25);
-- select * from students;
SELECT * FROM
(SELECT name FROM students WHERE GENDER = 'F' ORDER BY age DESC LIMIT 2)
UNION
(SELECT name FROM students WHERE GENDER = 'M' ORDER BY age DESC LIMIT 2);
Your online compliler uses not MySQL but SQLite!
Execute select sqlite_version(); - the output is '3.31.1'.
Use this:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY gender ORDER BY age DESC) rn
FROM students
)
SELECT name
FROM cte
WHERE rn <= 2;
This code is correct for SQLite.
PS. Add ORDER BY if needed.
For SQLite, both unioned queries, since they contain an ORDER BY clause, must be used as subqueries with an external SELECT clause and you can use an ORDER BY clause at the end which will be applied to the resultset of the union and will put all Fs at the top because they are alphabetically less than the Ms:
SELECT * FROM (SELECT * FROM students WHERE gender = 'F' ORDER BY age DESC LIMIT 2)
UNION
SELECT * FROM (SELECT * FROM students WHERE gender = 'M' ORDER BY age DESC LIMIT 2)
ORDER BY gender, age;
See the demo.

Union two queries ordered by newid

I have a table that stores employees (id, name, and gender). I need to randomly get two men and two women.
CREATE TABLE employees
(
id INT,
name VARCHAR (10),
gender VARCHAR (1),
);
INSERT INTO employees VALUES (1, 'Mary', 'F');
INSERT INTO employees VALUES (2, 'Jake', 'M');
INSERT INTO employees VALUES (3, 'Ryan', 'M');
INSERT INTO employees VALUES (4, 'Lola', 'F');
INSERT INTO employees VALUES (5, 'Dina', 'F');
INSERT INTO employees VALUES (6, 'Paul', 'M');
INSERT INTO employees VALUES (7, 'Tina', 'F');
INSERT INTO employees VALUES (8, 'John', 'M');
My attempt is the following:
SELECT TOP 2 *
FROM employees
WHERE gender = 'F'
ORDER BY NEWID()
UNION
SELECT TOP 2 *
FROM employees
WHERE gender = 'M'
ORDER BY NEWID()
But it doesn't work since I can't put two order by in the same query.
Why not just use row_number()? One method without a subquery is:
SELECT TOP (4) WITH TIES e.*
FROM employees
WHERE gender IN ('M', 'F')
ORDER BY ROW_NUMBER() OVER (PARTITION BY gender ORDER BY newid());
This is slightly less performant than using ROW_NUMBER() in a subquery.
Or, a fun method would use APPLY:
select e.*
from (values ('M'), ('F')) v(gender) cross apply
(select top (2) e.*
from employees e
where e.gender = v.gender
order by newid()
) e;
You cannot put an ORDER BY in the combinable query (the first one) of the UNION. However, you can use ORDER BY if you convert each one into a table expression.
For example:
select *
from (
SELECT TOP 2 *
FROM employees
WHERE gender = 'F'
ORDER BY newid()
) x
UNION ALL
select *
from (
SELECT TOP 2 *
FROM employees
WHERE gender = 'M'
ORDER BY newid()
) y
Result:
id name gender
--- ----- ------
5 Dina F
4 Lola F
2 Jake M
3 Ryan M
See running example at SQL Fiddle.

How to get unique records from 3 tables

I have 3 tables and I am trying to get unique results from all 3 tables (including other columns from each table).
I have tried union approach but that approach only works when I have single column selected from each table.
As soon as I want another corresponding column value from each table, I don't get unique values for the field I am trying to get.
Sample Database and query available here as well: http://www.sqlfiddle.com/#!18/1b9a6/10
Here is the example tables i have created.
CREATE TABLE TABLEA
(
id int,
city varchar(6)
);
INSERT INTO TABLEA ([id], [city])
VALUES
(1, 'A'),
(2, 'B'),
(3, 'C');
CREATE TABLE TABLEB
(
id int,
city varchar(6)
);
INSERT INTO TABLEB ([id], [city])
VALUES
(1, 'B'),
(2, 'C'),
(3, 'D');
CREATE TABLE TABLEC
(
id int,
city varchar(6)
);
INSERT INTO TABLEC ([id], [city])
VALUES
(1, 'C'),
(2, 'D'),
(2, 'E');
Desired result:
A,B,C,D,E
Unique city from all 3 table combined. By unique, I am referring to DISTINCT city from the combination of all 3 tables. Yes, the id is different for common values between tables but it doesn't matter in my use-case if id is coming from table A, B OR C, as long as I am getting DISTINCT (aka UNIQUE) city across all 3 tables.
I tried this query but no luck (city B is missing in the output):
SELECT city, id
FROM
(SELECT city, id
FROM TABLEA
WHERE city NOT IN (SELECT city FROM TABLEB
UNION
SELECT city FROM TABLEC)
UNION
SELECT city, id
FROM TABLEB
WHERE city NOT IN (SELECT city FROM TABLEA
UNION
SELECT city FROM TABLEC)
UNION
SELECT city, id
FROM TABLEC) AS mytable
try this. As this should give you distinct city with there first appear id:
select distinct min(id) over(partition by city) id, city from (
select * from TABLEA
union all
select * from TABLEB
union all
select * from TABLEC ) uni
You got the right idea, just wrap the UNION results in a subquery/temp table and then apply the DISTINCT
WITH TABLEE AS (
SELECT city, id FROM TABLEA
UNION
SELECT city, id FROM TABLEB
UNION
SELECT city, id FROM TABLEC
)
SELECT DISTINCT city
FROM TABLEE

SQL insert query for multiply rows with shared values

I have a simple table Users (name, city, country) and need to add several rows where some of values are the same (city, country). Is there a better way to insert data beside:
insert into Users (name, city, country) values
("John", "Paris", "France"),
("Anna", "Paris", "France"),
("Peter", "Paris", "France"),
("Mary", "Paris", "France")
Thank you
You can use a query like the following:
insert into Users (name, city, country)
select name, city, country
from (select 'John' as name union all
select 'Anna' union all
select 'Peter' union all
select 'Mary') as t1
cross join (select 'Paris' as city, 'France' as country) as t2
You should be able to use variables. So it would look like...
set #city="Paris";
set #country="France";
insert into Users(name, city, country) values
("John", #city, #country)
Although you could simplify this somewhat by using variables in your particular RDBMS syntax, you are stuck with inserting the same values into multiple rows of the table due to a design decision that you made when defining your Users table.
The problem is that your table is not normalized, meaning that the same information is present multiple times. A proper way of fixing this would be defining a table of countries, a table of cities referencing it, and changing Users table to reference Cities.
Your solution is correct normaly but try to replace " by ' else try it:
insert into Users (name, city, country)
select *
from (
select 'John', 'Paris', 'France' union all
select 'Anna', 'Paris', 'France' union all
select 'Peter', 'Paris', 'France' union all
select 'Mary', 'Paris', 'France'
) tmp