Return another value when row is inexistent - sql

In a database table with a structure like this :
Table 1
Name | Id
A 1
B 2
Table 2
Table1's ID | IntValue
1 11
2 66
now, there is a query which joins the 2 tables and outputs something like
A | 11
B | 66
but the problem is that when, let's say row (A,1) gets deleted from table1 the query outputs
| 11
B | 66
so instead of writing A it leaves it null because the row doesn't exist.
My question is: Instead of leaving it null, is there any option to make it write "Item Inexistent" or smth?
My database is Firebird 2.1.2

SELECT COALESCE(t1.name, 'Item nonexistent'), t2.intValue
FROM table2 t2
LEFT OUTER JOIN
table1 t1
ON t1.id = t2.id

Related

Sql want to get matching plus new records from tables

I am new to SQL queries, I have tables:
Table1:
Id | Flag
----+------
200 | 1
201 | 1
202 | 1
203 | 1
204 | 1
Table2:
Id | Flag
----+------
200 | 0
203 | 1
I want result like this:
Id | Flag
----+------
200 | 0
201 | 1
202 | 1
204 | 1
I have tried with left join but still I am not getting expected result.
It seems that you want a join where the Flag value from TableB is given priority over the value from TableA and where the Flag values do not match in both tables.
If that is the case, you could accomplish this with the use of a COALESCE() as well as a WHERE condition to remove items where the join fails and the matching Flag values):
SELECT a.ID,
COALESCE(b.Flag, a.Flag) Flag
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
AND (b.Flag IS NULL OR a.Flag <> b.Flag)
Example
You can see an interactive working example here, which given your data outputs the expected values:
You seem to want all rows except for the ones with "1" in both flag columns. Then, if available you want the flag in table2.
If this is a correct interpretation:
select t1.id, coalesce(t2.flag, t1.flag)
from table1 t1 left join
table2 t2
on t1.id = t2.id
where t1.flag <> 1 or
(t2.flag is null or t2.flag <> 1)
Here is a db<>fiddle.

Query table based on the value of another tables column

I have read-only access to a database and there are two tables that contain information I need. both tables have the same numbers in row a in referee to an account. I want to query the result of all accounts in table 1 that have "AD" in column B and where the account has values "4" in column C in of table 2. below is an example.
table 1 |
-------- |
A | B | |
_______ |
1 AC |
2 AD |
3 AC |
4 AD |
___________
table 2 |
-------- |
A | B | C |
__________|
1 AB 4 |
2 AB 5 |
3 AB 4 |
4 AB 4 |
I have tried the query
SELECT * FROM Table 1 WHERE column B = 'AD' and WHERE column C = '4' FROM TABLE 2
you can use inner Join instead,
Like this:
SELECT
t1.*
FROM
Table1 t1 JOIN Table2 t2 ON t1.A = t2.A
WHERE
t2.C = 4 AND t1.B = 'AD'
There isn't quite enough info here for me to help. There isn't common data between the two tables to link them.
Your query above is missing a join between the two tables, and you only need to state the where clause once, additional criteria can be added by using 'and.....'

SQL Join On Columns of Different Length

I'm trying to join two tables together in SQL where the columns contain a different number of unique entries.
When I use a full join the additional entries in the column joined on are missing.
The code I'm using is (in a SAS proc SQL):
proc sql;
create table table3 as
select table1.*, table2.*
from table1 full join table2
on table1.id = table2.id;
quit;
Visual example of problem (can't show actual tables as contain sensitive data)
Table 1
id | count1
1 | 2
2 | 3
3 | 2
Table 2
id | count2
1 | 4
2 | 5
3 | 6
4 | 2
Table 3
id | counta | countb
1 | 2 | 4
2 | 3 | 5
3 | 2 | 6
- | - | 2 <----- I want don't want the id column to be blank in this row
I hope I've explained my problem clearly enough, thanks in advance for your help.
The id from table 1 is blank because the row from table2 has no match in table 1. Try looking at the output from this query:
select coalesce(table1.id, table2.id) as id, table1.count1, table2.count2
from table1 full join table2
on table1.id = table2.id;
Coalesce works from left to right returning the first non null value (it can take more than 2 arguments). If the id in table 1 is null it uses the id from table 2 instead
I recommend also to alias all tables in queries, so I’d have written this:
SELECT
COALESCE(t1.id, t2.id) as id,
t1.count1,
t2.count2
FROM
table1 t1
FULL OUTER JOIN
table2 t2
ON
t1.id = t2.id;
Simply select coalesce(t1.id, t2.id), will return the first non-null id value.

does LEFT JOIN return same row count as left table?

SELECT *
FROM t1
LEFT JOIN t2 ON t1.fk = t2.id;
Will it always return the same row count as that of t1 ?
The contract of a left join states that, in the absence of a WHERE clause which might remove records from the result set, all records which appear in the left side of the join will appear at least once. Consider the following data set:
t1
id | fk
1 | 1
2 | 2
t2
id | value
1 | 1
1 | 2
Your query would return this result set:
id | fk | id | value
1 | 1 | 1 | 1
1 | 1 | 1 | 2
2 | 2 | NULL | NULL
Note carefully that the first table's fk = 2 did not match anything to the second table. This record still appears in the result set, but all columns coming from the second table are NULL. Also, note that fk = 1 records appear twice, because that single record in the first table matched twice to the second table.
If t2.id has a unique constraint, the row count will always be the same as if the join isn't there. If it's not unique, you will get multiple duplicates of the same t1 row, each with its own corresponding t2 row. Whether that's good enough for you depends on your database design.
Will it always return the same row count as that of t1?
No.
A LEFT JOIN is a join and as such will match one row from one table to multiple rows of another table. The result set may have the same number of rows or more rows.
Not necessarily:
CREATE TABLE t1(id int, fk int);
INSERT INTO t1 VALUES (1,1);
CREATE TABLE t2(id int, value int);
INSERT INTO t2 VALUES(1,1),(1,2);
SELECT *
FROM t1
LEFT JOIN t2 ON t1.fk = t2.id;
returns 2 rows:
id fk id value
1 1 1 1
1 1 1 2

Delete subtable from a table, SQL

What is the most clever way to delete tuples from table1, that are in the second table,
if the second table is not a part of initial database, but a result of some really big query?
table1 *this table is a result of some query
------------- -------------
| id1 | id2 | | id1 | id2 |
------------- -------------
| 1 2 | | 5 6 |
| 3 4 | | 1 2 |
| 5 6 | | 11 12 |
| 7 8 | -------------
| 9 10 |
| 11 12 |
| 13 14 |
-------------
I came up with
delete from table1
where id1 in (select id1 from ( really long query to get a second table))
and id2 in (select id2 from (the same really long query to get a second table));
It works, but I feel like I'm doing it way too wrong, and not keeping the query DRY.
And would the way you suggest work the same if table1 had an additional column, for example "somecol"?
IMO, You can use EXISTS statement like this:
DELETE FROM table1
WHERE EXISTS (
SELECT 1
FROM (<your long query>) AS dt
WHERE table1.id1 = dt.id1
AND table1.id2 = dt.id2);
[SQL Fiddle Sample]
One method is to use with, delete and exists:
with secondtable as (
<your query here>
)
delete from table1
where exists (select 1
from secondtable st
where table1.id1 = st.id1 and table1.id2 = st.id2
);
A Correlated Subquery using EXISTS allows matching multiple columns:
delete
from table1
where exists
( select * from
(
"really long query"
) as t2
where table1.id1 = t2.id1 -- correlating inner and outer table
and table1.id2 = t2.id2 -- similar to a join-condition
)