Linking two Columns in the same table - sql

I have the following columns in my table:
Title | Title Root
-------|--------------
A | null
B | A
C | D
D | null
E | null
F | E
I need to be able to have my query see that rows like B,C, and F have a value in Title_Root and display the corresponding title of that title_root. For example: B has Title_root = A. So then display the Title A. I don't want it to display B's title though.
I hope this makes sense. I just started doing queries.

Looks like a simple outer join:
select t1.title,
t2.title_root
from the_table t1
left join the_table t2 on t2.title_root = t1.title
Or if you only want to see one title:
select coalesce(t2.title_root, t1.title) as title
from the_table t1
left join the_table t2 on t2.title_root = t1.title

It seems like a simple update statement should do the trick:
UPDATE Table
SET title = title_root
WHERE title_root is not null
Hope this helps.

Related

Could i use right outer join and inner join together?

I'm trying to get the data from 3 tables but i think i need to use inner join (to join TABLE1 and TABLE2) and right outer join because i need all information from TABLE3 but i don't know how to do it. I tried this:
select a.TABLE1_ID, e.TABLE2_ID,f.TABLE3_ID
from TABLE1 as a, TABLE2 as e, TABLE3 as f
where a.TABLE1_ID = e.TABLE2_ID and a.TABLE1_COL = f.TABLE3_ID
UNION ALL
SELECT f.TABLE3_ID, NULL
FROM TABLE3 as f
WHERE NOT EXISTS (
SELECT * FROM TABLE1 as a
WHERE a.TABLE1_COL = f.TABLE3_ID);
But i get the following error:
The operands of a set operator or a VALUES clause do not have the same number of columns.. SQLCODE=-421, SQLSTATE=42826, DRIVER=4.19.56
How could i do it? Is it possible?
**EDIT:
The following is the result that i would like to get:
a.TABLE1_ID | e.TABLE2_ID | f.TABLE3_ID
----------------------------------------
AFR123 | AFR123 | MM145FR123
AFR124 | AFR124 | MM145FR124
NULL | NULL | MM145FR125
NULL | NULL | MM145FR126
You are describing LEFT JOINs:
select a.TABLE1_ID, e.TABLE2_ID, f.TABLE3_ID
from TABLE3 f left join
TABLE1 a
ON a.TABLE1_ID = f.TABLE3_ID left join
TABLE2 e
on a.TABLE1_ID = e.TABLE2_ID ;
As a note: If there is a row in a that matches f but has no matching row in e, then this keeps the values from a. If you using INNER JOIN followed by RIGHT JOIN, you won't have the values in the intermediate table. Usually having such values is desired.

SQL condition for a join

I've created an SQL query (Oracle) that is a join of 2 tables, and this table has entries related to users joining or leaving a particular instance.
So, let's say that the table looks something like:
+------------+--------+
| User_ID | State |
+------------+--------+
| 101 | Joined |
+------------+--------+
| 102 | Joined |
+------------+--------+
| 101 | Left |
+------------+--------+
As you can see, user 101 Joined, but then left. Is it possible to somehow specify that in case user left, then all entries related to this user are removed from the table (user ID is unique), but in case there is only entry saying that user Joined, then user will stay in the table?
I am new to SQL, my apologies if the question lacks some details, please feel free to ask for clarification.
To remove the records pertaining to users that have left, you might try the following:
DELETE FROM mytable m1
WHERE EXISTS ( SELECT 1 FROM mytable m2
WHERE m2.user_id = m1.user_id
AND m2.state = 'Left' );
Alternately (this might make things a bit more clear):
DELETE FROM mytable m1
WHERE m1.user_id IN ( SELECT m2.user_id
FROM mytable m2
WHERE m2.state = 'Left' );
Hope this helps.
You can get the list of ID that has the State "Left" and then delete those IDs
DELETE FROM tablename
WHERE user_id IN (SELECT user_id
FROM tablename
WHERE state = "left")
You can do something like this:
select t.*
from t
where not exists (select 1 from t t2 where t2.id = t.id and t.state = 'Left');
You can easily turn this to a delete:
delete t
where exists (select 1 from t t2 where t2.id = t.id and t.state = 'Left');

SQL Server: how can I count values in one field different from another, with multiple values for same identifier?

I have two tables with one common column, and an identifying value that can be duplicate (several observations of same document).
An example:
TableA:
A_identifier | Value
-------------+-------
1 | A
1 | B
TableB:
B_identifier | A_identifier | Value
-------------+--------------+-------
1 | 1 | A
2 | 1 | B
3 | 1 | B
4 | 1 | C
The above example illustrates the type of situation I am looking for in my data - we have a case in TableA with multiple values, of which some are the same in TableB and some are not. So TableA.Value and TableB.Value represent the same concept.
I want to know for each TableA.A_identifier, how many rows of TableB have different values than TableA.Value. If there was only one observation per A_identifier, this could be solved with a not, but the multiple possible values prevent this.
What I have thought about doing is something like this (which does not work):
select distinct
b.B_identifier, a.A_identifier
from
TableB b
join
TableA a in b.A_identifer = a.A_identifier and b.Value != a.Value
While the query technically works, it returns the wrong result - it counts all the cases where the values in TableA and TableB are different in a given row. However, I want it to only count the values in TableB which are not present at all in TableA for each A_identifier.
I tried replacing the != with not in which is what I would do for a static parameter. This syntax is not supported.
I hope my question makes sense, and that somebody can help. Thank you in advance.
Try this query if it works for you,
SELECT COUNT(b.A_identifier)
FROM TableB b
LEFT JOIN TableA a
ON b.A_identifier = a.A_identifier
AND b.Value = a.Value
WHERE a.A_identifier IS NULL -- filters out inexisting value
AND EXISTS (SELECT 1
FROM TableA c
WHERE b.A_identifier = c.A_identifier) -- shows only A_identifier
-- that is present in TableA
However, if you want to get the count for each Value
SELECT b.A_identifier, b.Value, TOTAL_COUNT = COUNT(b.A_identifier)
FROM TableB b
LEFT JOIN TableA a
ON b.A_identifier = a.A_identifier
AND b.Value = a.Value
WHERE a.A_identifier IS NULL
AND EXISTS (SELECT 1
FROM TableA c
WHERE b.A_identifier = c.A_identifier)
GROUP BY b.A_identifier, b.Value
Use NOT EXISTS
select t1.A_identifier, count(t2.value)
from TableA t1
left join TableB t2 on t1.A_identifier = t2.A_identifier and
NOT EXISTS (
select 1
from TableA t3
where t3.A_identifier = t2.A_identifier and
t3.Value = t2.Value
)
group by t1.A_identifier
How about the following SQL?
select distinct TableA.A_identifier,
(select count(*) from TableB
where TableB.A_identifier = TableA.A_identifier
and not exists(
select * from TableA where A_identifier = TableB.A_identifier
and Value = TableB.Value)
)
as TableB_Rows
from TableA

Query to output not existing data

Table A:
id Name
1 a
2 b
3 c
4 d
5 e
Table B:
id Name
3 c
4 d
5 e
Here, id is the primary key connected to Table B.
I need output like this:-
id
1
2
That means, which ids in Table A are not present in Table B
Use EXCEPT operator:
select id from tableA
except
select id from tableB
You can use a left join, which will preserve all records on the left side and associate them with null if no matching record is available on the right side.
This way you can then filter on the right side columns to be null to get the desired outcome
select t1.id
from tableA t1
left join
tableB t2
on t1.id = t2.id
where t2.id is null
Use NOT EXISTS in WHERE clause
SELECT id FROM TableA A
WHERE NOT EXISTS(SELECT 1 FROM TableB B WHERE A.id = B.Id )
Using Not in statement.
Try this:-
Select id from TableA
where id not in (Select id from TableB);
You can use minus:
select * from tableA
minus
select * from tableB

SQL: select all unique values in table A which are not in table B

I have table A
Id | Name | Department
-----------------------------
0 | Alice | 1
0 | Alice | 2
1 | Bob | 1
and table B
Id | Name
-------------
0 | Alice
I want to select all unique Ids in table A which do not exist in table B. how can I do this?
select distinct id
from TableA a
where not exists (
select id
from TableB
where id = a.id
)
Just to provide a different solution than NOT IN :
SELECT DISTINCT A.Id
FROM A
LEFT OUTER JOIN B
ON A.Id = B.Id
WHERE B.Id IS NULL
The "good" solution is usually MINUS or EXCEPT, but MySQL doesn't support it.
This question was asked a few time ago and someone posted an article comparing NOT IN, NOT EXISTS and LEFT OUTER JOIN ... IS NULL. It would be interesting if someone could find it again!
The most efficient answer is to use a left join, as using "NOT IN" can sometimes prevent a query from using an index, if present.
The answer in this case would be something like
SELECT DISTINCT
*
FROM
TableA a
LEFT JOIN
TableB b
ON
a.Id = b.Id
WHERE
b.Id IS NULL
Alternatively, this is more readable than a left join, and more efficient than the NOT IN solutions
SELECT * FROM TableA a where NOT EXISTS (SELECT * FROM TableB where Id = a.Id)
I'd use a NOT EXISTS Like this:
SELECT A.Id
FROM TableA A
WHERE NOT EXISTS (SELECT B.Id FROM TableB B WHERE A.Id = B.Id)
GROUP BY A.Id
SELECT DISTINCT Id FROM A WHERE Id NOT IN (SELECT ID FROM B);
SELECT DISTINCT Id FROM A WHERE Id NOT IN(SELECT DISTINCT Id FROM B);
The subquery will get all the IDs in B. The group by...having will get all the unique IDs in A that are also not in B.
select *
from A
where id not in
(
select distinct id
from B
)
group by ID
having count(*) > 1;