SQL Statement with a simple join - sql

I have problems to do a SQL statement. I have the following example-tables:
Table 1:
ID - | - Name
1; ABC
2; DEF
3; GHI
Table 2:
ID - | - Bool
1; true
1; false
2; true
3; false
3; false
I want to join the tables but show only the entities, which have NO false in table 2. Example:
Is there a false and a true in one entity, I don't want to have the Entity in my Result. Are there true true in one entity, it is ok.
My Problem are Entitys, which have true and false in table 2...
Thank you for helping!

Since your IDs have duplicates in table2, you'll have to do some inventory/counting:
SELECT table1.ID, table1.Name,
SUM(table2.Bool = false) as trues,
SUM(table1.Bool = true) as falses
FROM table1
INNER JOIN table2 ON table1.ID = table2.ID
GROUP BY table1.ID
HAVING falses = 0

This will give you all records that have a TRUE record in Table 2 but no FALSE record:
SELECT ID, Name
FROM Table1 t1
WHERE EXISTS
(
SELECT NULL
FROM Table2 t2
WHERE t2.ID = t1.ID
AND t2.Bool = 'true'
)
AND NOT EXISTS
(
SELECT NULL
FROM Table2 t2
WHERE t2.ID = t1.ID
AND t2.Bool = 'false'
)

I do not have a DB handy, but I wonder if this would work:
select t1.id, t1.name
from table1 t1
inner join table2 t2 on t1.id = t2.id
where t1.id not in (select id from table2 where Bool = 'false')

If the column 'bool' on table 2 is truly the boolean data type, which is 1 if true, and 0 if false, then any ID having a minimum bool value not equal to 0 must have no false values.
So you could run: (see fiddle: http://sqlfiddle.com/#!2/76639/1/0)
select t1.id, t1.name
from table_1 t1
join (select id from table_2 group by id having min(bool) <> 0) v
on t1.id = v.id

Related

Some kind of IF condition in INSERT

I have next tables:
table1 table2
id. value position id state
1. false
What I need is to insert data in to table1 if state from table2 is true.
Something like:
INSERT INTO table1(value, position)
VALUES('someVal', 3)
IF table2.id = 1 AND table2.state = true
Do you want exists?
INSERT INTO table1(value, position)
SELECT v.value, v.position
FROM (VALUES('someVal', 3)) v(value, position)
WHERE EXISTS (SELECT 1 FROM TABLE2 t2 WHERE t2.id = 1 AND t2.state = true);
You can select only item where table2.State = true before inserting
If you have your data comming from another table it would look like this
INSERT INTO table1(value, position)
SELECT ValueId, Value
FROM TableValue
INNER JOIN Table2
ON TableValue.ValueID = Table2.ID
WHERE table2.state = true

Conditional Join with replace and case

I have two tables that I want to join.
The case is in table 1 the default value is 1 then in table 2 the default value is 0
Table 1 Table 2
-------- ---------
1 0
1232342 1232342
1241232 1231231
I want to join table 1 and table 2 with condition that if table 2 is 0 then it will be replaced to 1.
SELECT T1.ID
FROM TABLE1 T1, TABLE2 T2
WHERE T1.ID = REPLACE(CASE WHEN T2 = 0 THEN 1 ELSE T2.ID END, 'X', 'E')
with this statement it does not return the other id's that are not 0 or 1
expected output
Table 1
--------
1
1232342
Use a join with a CASE. replace() is for string values:
select t1.*
from table1 t1
join table2 t2 on t1.id = case when t2.id = 0 then 1 else t2.id end;
use case when and sub-query
select t1.* from table1 t1 join
(
select case when t2.id=0 then 1 else t2.id end as id from table2 t2
) as t3 on t1.id=t3.id
Try using case when :
SELECT *
FROM TABLE1 T1 inner join TABLE2 T2
on T1.ID = (CASE WHEN T2.ID =0 THEN 1 ELSE T2.ID END)
Switch to modern, explicit JOIN syntax. Skip the case expression, simply use AND/OR instead:
SELECT T1.ID
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.ID = T2.ID OR (T1.ID = 1 and T2.ID = 0)
Or use INTERSECT:
SELECT ID FROM TABLE1
INTERSECT
SELECT case when ID = 0 then 1 else id end from TABLE2

Execute different statements in one query on the condition

Say we have two Users with ID = 1 and ID = 2
I know the ID of the current User and I need to execute different select statements depending on the ID.
if ID = 1
select a from table1
else if ID = 2
select b from table2
else
select c from table3
Is there a way to put this logic into single SQL query?
You can use union with appropriate where conditions.
select a from table1 where id = 1
union all
select b from table2 where id = 2
union all
select c from table3 where id not in (1,2)
or if the tables can be joined
select
case when t1.id = 1 then t1.a
when t2.id = 2 then t2.b
else t3.c end
from table1 t1
join table2 t2 on t1.id = t2.id
join table3 t3 on t1.id = t3.id

How make a union of two columns with different value of fields

I Have two columns from different selects in sql server
Table 1
ID Name Bit
.... ............ .....
1 Enterprise 1 False
2 Enterprise 2 True
3 Enterprise 3 False
Table 2
ID Name Bit
.... ............ .......
1 Enterprise 1 True
2 Enterprise 2 False
3 Enterprise 3 False
expected result
ID Name Bit
.... ............ ......
1 Enterprise 1 True
2 Enterprise 2 True
3 Enterprise 3 False
the problem is make a union between the two tables and the bit column prevail fields that are true
Any ideas?
I would suggest casting it to an int:
select id, name, cast(max(bitint) as bit) as bit
from ((select id, name, cast(bit as int) as bitint
from table1
) union all
(select id, name, cast(bit as int) as bitint
from table2
)
) t12
group by id, name;
With your data, you can also do it using join:
select t1.id, t1.name, (t1.bit | t2.bit) as bit
from table1 t1 join
table2 t2
on t1.id = t2.id and t1.name = t2.name;
This assumes all the rows match between the two tables (as in your sample data). You can do something similar with a full outer join if they don't.
You can make a left join on the other table to exclude the records that should be used from the other table:
select
t1.ID, t1.Name, t1.Bit
from
[Table 1] t1
left join [Table 2] t2 on t2.ID = t1.ID
where
t1.Bit = 1 or t2.Bit = 0
union all
select
t2.ID, t2.Name, t2.Bit
from
[Table 2] t2
left join [Table 1] t1 on t1.ID = t2.ID
where
t1.bit = 0 and t2.Bit = 1
(If there is a True in both tables or a False in both tables for an item, the record from Table 1 is used.)
SELECT Table1.ID, Table1.Name, IIF(Table1.[Bit]>0 OR Table2.[Bit]>0,1,0) AS [Bit]
FROM
(VALUES(1,'Enterprise 1',0),(2,'Enterprise 2',1),(3,'Enterprise 3',0)) as Table1(ID,Name,Bit),
(VALUES(1,'Enterprise 1',1),(2,'Enterprise 2',0),(3,'Enterprise 3',0)) as Table2(ID,Name,Bit)
WHERE Table1.ID = Table2.ID
It seems to me that you are just doing a logical OR operation on the Bit column and calling it UNION.

Combine two SQL select into one

I have two SQL SELECT COUNT statements:
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = false AND t2.flag2 = true;
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = true AND t2.flag2 = false;
As can be seen the only difference of these two statements are the flipped condition.
But what I want to do is to combine the two statements into one so that the output becomes one table with two columns, the first column contains the result of the first statement and the second column contains the result of the second statement. Something like:
count1 | count 2
-------------------------
3456 | 9864
I use PostgreSQL by the way. Can someone let me know how to do this?
Many thanks
This should do it for you. I'm not to familiar with PostgreSql but I think it will work.
SELECT
SUM(CASE WHEN t1.Flag1 = false AND t2.flag2 = true THEN 1 ELSE 0 END) Count1,
SUM(CASE WHEN t1.Flag1 = true AND t2.flag2 = false THEN 1 ELSE 0 END) Count2
FROM
table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
If you really need it this way (use two sql queries and combine them) then:
select * from
(SELECT COUNT(*) FROM table1 t1 INNER JOIN table2 t2 ON t2.id = t1.rowid WHERE t1.flag1 = false AND t2.flag2 = true) a,
(SELECT COUNT(*) FROM table1 t1 INNER JOIN table2 t2 ON t2.id = t1.rowid WHERE t1.flag1 = true AND t2.flag2 = false) b
Based on your SQL, this would be better solution:
select
sum (case when not t1.flag1 and t2.flag2 then 1 else 0 end) as count1,
sum (case when t1.flag1 and not t2.flag2 then 1 else 0 end) as count2
FROM
table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
You can also cast boolean type to integer and shorten the sql (true::int = 1, false::int = 0):
select
sum((flag1::int<flag2::int)::int) count1,
sum((flag1::int>flag2::int)::int) count2
from
table1 t1
join table2 t2 ON t2.id = t1.rowid
And because true > false and false < true (at least in PostgreSQL) you can write:
select
sum((flag1 < flag2)::int) count1,
sum((flag1 > flag2)::int) count2
from
table1 t1
join table2 t2 ON t2.id = t1.rowid
Select * from
(
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = false AND t2.flag2 = true) tab1,
(
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = true AND t2.flag2 = false) tab2