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
Related
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
In T1 I have a 50 ID'ss. I'm trying to find which ones are in T2. And add row name "test" next to ID with info about occurrence in T2. But when I put my code I receive only ID's which are included in T2. What I`m doing wrong?
SELECT DISTINCT t1.id, CASE WHEN t1.id IS NULL THEN 0 ELSE 1 END AS test
FROM t2
JOIN t1 ON t2.id = t1.id
You can use outer join:
SELECT DISTINCT t1.id, CASE WHEN t2.id IS NULL THEN 0 ELSE 1 END AS test
FROM t1 LEFT JOIN t2 ON t2.id = t1.id
Use exists:
select t1.*,
(case when exists (select 1 from t2 where t2.id = t1.id) then 1 else 0 end) as flag
from t1;
Note that select distinct is not needed. That construct just slows down queries, if it is not needed.
Use Left Join to get the unmatched rows as well.
select t1.id
, case when t2.id is null then 0 else 1 end as test
from t1
left outer join t2
on t1.id = t2.id
I have this SQL in DB2 and want to avoid repeating the conditions in the EXISTS clause in the second UNION, as the conditions can be fairly large. How do I do that? Any help is greatly appreciated.
select id from table t where t.given_name = 'good' and t.time = 1 and exists
(select 1 from table t1 where t1.id = t.id and t1.surname = 'OK') union
select id from table t where t.given_name = 'good' and t.time = 2 and not exists
(select 1 from table t1 where t1.id = t.id and t1.surname = 'OK')
I think this could be also achieve via where clause only
where given_name = 'good' and
(times = 1 and surname = 'OK') or
(times = 2 and surname <> 'OK')
Why are you using union? How about just doing this?
select id
from table t
where t.given_name = 'good' and
t.time in (1, 2) and
exists (select 1 from table t1 where t1.id = t.id and t1.surname = 'OK');
If id could have duplicates, use select distinct in the outer query.'
EDIT:
I think I misread the original query. The logic would be:
select id
from table t
where t.given_name = 'good' and
( (t.time = 1 and exists (select 1 from table t1 where t1.id = t.id and t1.surname = 'OK')
) or
(t.time = 2 and not exists (select 1 from table t1 where t1.id = t.id and t1.surname = 'OK')
)
)
Use a WITH clause to remove redundancy
with t2 as (select * from t1 where surname = 'OK')
select id from table t where t.given_name = 'good' and t.time = 1 and exists
(select 1 from table t2 where t2.id = t.id) union
select id from table t where t.given_name = 'good' and t.time = 2 and not exists
(select 1 from table t2 where t2.id = t.id)
;
and you can do the same for the other table too if needed
with t2 as (select * from t1 where surname = 'OK')
, tt as (select * from t where given_name = 'good')
select id from table tt where tt.time = 1 and exists
(select 1 from table t2 where t2.id = tt.id) union
select id from table tt where tt.time = 2 and not exists
(select 1 from table t2 where t2.id = tt.id)
;
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
I have 2 tables:
T1 (id, flag1)
T2 (id, amount, date, flag2, t1_id);
I have the following query:
SELECT T1.id, ROUND(COALESCE(SUM(T2.amount), 0), 2) AS spent_amount
FROM T1
LEFT JOIN T2 ON T2.t1_id = T1.id
WHERE T2.date <= '2014-01-01' AND T2.flag2 = 't' AND T1.flag1 = 't'
GROUP BY T1.id
The problem is that I want to have a row in the result such as: id = 123, spent_amount = 0 in case where I have an entrance in T1, but it has no connected rows in T2.
Having a WHERE clause on your T2 it will filter out all NULLS:
SELECT T1.id, ROUND(COALESCE(SUM(T2.amount), 0), 2) AS spent_amount
FROM T1
LEFT JOIN T2
ON T2.t1_id = T1.id
AND T2.date <= '2014-01-01'
AND T2.flag2 = 't'
WHERE T1.flag1 = 't'