Case for the whole dataset in sql table - sql

Have a table like that. Let's pretend it is full table and we dont have any other rows:
ID Place
1 A
1 B
2 C
3 D
How can I perform such thing:
ID Place YesNo
1 A 1
1 B 1
1 C 0
1 D 0
2 A 0
2 B 0
2 C 1
2 D 0
3 A 0
3 B 0
3 C 0
3 D 1
For yes/no I need CASE statement but how to do the rest- full join table on itlself or some other options?
Thanks!

You can achieve that with two subqueries which each list the possible values of one of the columns. The two results should then be crossed to get all combinations. Finally outer join this with the original table to see which combinations actually occur:
SELECT first.ID,
second.Place,
CASE WHEN mytable.ID IS NULL THEN 0 ELSE 1 END AS YesNo
FROM (
SELECT DISTINCT ID
FROM mytable
) first
CROSS JOIN (
SELECT DISTINCT Place
FROM mytable
) second
LEFT JOIN mytable
ON mytable.ID = first.ID
AND mytable.Place = second.Place
ORDER BY first.ID,
second.Place
Here is an SQL fiddle

Related

Excluding Certain Matching Rows in an SQL Join

My issue somewhat complex, so I will explain using simplified versions of my tables.
This is Table 1:
Value L AID OID
A 1 1
B 2 1
C 3 1
D 4 1
E 2 1
F 2 2
G 2 3
H 2 4
This is Table 2:
Value R AID OID VAR
Z 0 1 0
Y 1 1 1
X 2 1 1
W 4 1 1
V 0 2 0
U 1 2 1
T 3 2 1
I would like to join these tables such that any row in Table 1 that doesn’t have a corresponding row in Table 2 with both matching AID and OID is returned in a join to the row with a matching OID and an AID and VAR of 0. In this example it would look like this:
Value L Value R AID OID VAR
C Z 3 1 0
F V 2 2 0
H V 4 2 0
I am not certain how to tackle this. Specifically, not sure how to stop the rows that have a matching AID and OID from showing up in my join, and only having the rows that don't have that match. Any advice would be appreciated.
I think you want not exists:
select t1.*
from table1 t1
where not exists (select 1
from table2 t2
where t2.aid = t1.aid and t2.oid = t1.oid and t2.var = 0
);

SQL apply different where condition (filter) for each group in table

i have following SQL table A in my database:
index, group, foo
1 A 2
2 A 2
3 A 0
4 A 1
5 B 2
6 B 1
7 C 1
There are few more groups and I need to write a query based on this filter table B. For each group in table A it's index should be equal or greater than index_egt from table B for the same group.
If the group is not listed in table B, the group won't be filtered.
index_egt, group
3 A
5 B
Expected result:
index, group, foo
3 A 0
4 A 1
5 B 2
6 B 1
7 C 1
Try this, the A.index>=B.index_egt will handle cases where the group is listed in TableB and the B.index_egt IS NULL will handle cases where the group is not listed:
SELECT
A.index,
A.group,
A.foo
FROM TableA AS A
LEFT JOIN TableB AS B ON A.group=B.group
WHERE A.index>=B.index_egt
OR B.index_egt IS NULL
select
a.*
from
A a
left join
B b ON b.group = a.group
where
a.index >= b.index_egt OR b.index_egt IS NULL
I always like this trick with coalesce
SELECT a.*
FROM a_table_with_no_name a
LEFT JOIN b_table_with_no_name b ON b.group = a.group
WHERE a.index >= COALESCE(b.index_egt,a.index)

Which kind of join do I need to use here?

For every row in table Y, I need a copy of the current row in Table X, taking field 1 from Table Y.
Table X
Field 1 Field 2
null A
null B
null C
Table Y
Field 1
1
2
3
Desired output
Field 1 Field 2
1 A
1 B
1 C
2 A
2 B
2 C
3 A
3 B
3 C
Looks like a cross join:
select y.field1, x.field2
from x cross join
y;
Looks like an unconditional select of both tables without matching ids
Something like
select tableY.column1, tableX.column2
from tableY, tableX
order by tableY.column1 asc, tableX.column2 asc
should do it.
BTW. Was this a school question, because then I should not have answered this.
Try this query:
SELECT #Tabley.Field1 , #TableX.Field2
FROM #TableX ,#Tabley

select data having same id

id idtest result
1 1 2
1 2 1
1 3 2
2 1 2
2 2 1
2 3 1
3 1 1
3 2 2
3 3 1
Would like to get all the rows with the same IDs that matches the condition.
For example: get all the rows with the same id where (idTest=2 and result=1) and (idTest=3 and result=2)
result:
id idtest result
1 1 2
1 2 1
1 3 2
What would be the query???
Thanks!
Do you mean this?
SELECT * FROM table WHERE id = 1 and (result = 1 OR result = 2)
How about his:
SELECT *
FROM table WHERE (idTest = 2 OR idTest = 3) AND (result=1 OR result=2)
ID test res
1 1 2
1 2 1
1 3 2
2 1 1
2 2 2
2 3 2
3 1 1
3 2 2
3 3 1
Sorry. This would be my table. and Would like to get all the rows with the same IDs that matches the condition. For example: get all the rows with the same id where (test=2 and res=1) and (test=3 and res=2)
Result:
ID test res
1 1 2
1 2 1
1 3 2
What would be the query in order to get the three rows ?? Thanks!
You can use EXISTS:
SELECT id, idTest, result
FROM dbo.TableName t
WHERE EXISTS
(
SELECT 1 FROM dbo.TableName t2
WHERE t.id = t2.id
AND(
( t2.idTest=2 AND t2.result=1 )
OR
( t2.idTest=3 AND t2.result=2 )
)
)
Demo
Update: result is different:
id idTest result
1 1 2
1 2 1 <-- satisfies your condition
1 3 2 <-- satisfies your condition
2 1 2
2 2 1 <-- satisfies your condition
2 3 1
So either my understanding was incorrect or your expected result. I have also all ID=2 because the second id-2 row matches the condition.
You seem to want all rows for id's that have rows with that particular combination. What about:
with ids as (
select id
from mytable
where (idTest=2 and result=1) or (idTest=3 and result=2)
group by id
having count(id) = 2
)
select mytable.* from mytable
inner join ids
on ids.id = mytable.id
This gets a list of id's where both conditions apply, and then gets all rows for those id's.
SqlFiddle
SELECT *
FROM table t1
WHERE EXISTS (SELECT 1 FROM table WHERE id = t1.id AND idtest = 2 AND result = 1)
AND EXISTS (SELECT 1 FROM table WHERE id = t1.id AND idtest = 3 AND result = 2)
Just keep adding more AND EXISTS if you need more
Or you can use IN if it makes more sense to you
SELECT *
FROM table
WHERE id IN (SELECT id from table where idtest = 2 and result = 1)
AND id IN (SELECT id from table where idtest = 3 and result = 2)
do you need a method that treats the condition(s) in a generic way, like if they're values in another table? Or do you only need a way to pull results of two independent conditions?
If the latter, then this should work:
SELECT
id
FROM
(SELECT id
FROM tbl
WHERE idTest=2 AND RESULT=1) cond1 INNER JOIN
(SELECT id
FROM tbl
WHERE idTest=3 AND RESULT=2) cond2 ON
cond1.id = cond2.id
otherwise, if your conditions are generic and stored in a table, you'd need something like:
SELECT
id
FROM
(SELECT id
FROM tbl FULL OUTER JOIN conditions c
WHERE c.isUseMe = 1 AND c.SEQ = 1 AND idTest=c.idTestVal AND result=c.resultVal) cond1 INNER JOIN
(SELECT id
FROM tbl FULL OUTER JOIN conditions c
WHERE c.isUseMe = 1 AND c.SEQ = 2 AND idTest=c.idTestVal AND result=c.resultVal) cond2 ON
cond1.id = cond2.id
if the 4 values are passed in as parameters, you'd need something like:
SELECT
id
FROM
(SELECT id
FROM tbl
WHERE idTest=#idTestVal1 AND result=#resultVal1) cond1 INNER JOIN
(SELECT id
FROM tbl
WHERE idTest=#idTestVal2 AND result=#resultVal2) cond2 ON
cond1.id = cond2.id

how to prevent duplicates with inner join query (Postgres)

I am trying to understand how to create a query to filter out some results based on an inner join.
Consider the following data:
formulation_batch
-----
id project_id name
1 1 F1.1
2 1 F1.2
3 1 F1.3
4 1 F1.all
formulation_batch_component
-----
id formulation_batch_id component_id
1 1 1
2 2 2
3 3 3
4 4 1
5 4 2
6 4 3
7 4 4
I would like to select all formulation_batch records with a project_id of 1, and has a formulation_batch_component with a component_id of 1 or 2. So I run the following query:
SELECT formulation_batch.*
FROM formulation_batch
INNER JOIN formulation_batch_component
ON formulation_batch.id = formulation_batch_component.formulation_batch_id
WHERE formulation_batch.project_id = 1
AND ((formulation_batch_component.component_id = 2
OR formulation_batch_component.component_id = 1 ))
However, this returns a duplicate entry:
1;"F1.1"
2;"F1.2"
4;"F1.all"
4;"F1.all"
Is there a way to modify this query so that I only get back the unique formulation_batch records which match the criteria?
EG:
1;"F1.1"
2;"F1.2"
4;"F1.all"
Thanks for your time!
In this case it is possible to apply the distinct before the join possibly making it more performant:
select fb.*
from
formulation_batch fb
inner join
(
select distinct formulationbatch_id
from formulation_batch_component
where component_id in (1, 2)
) fbc on fb.id = fbc.formulationbatch_id
where fb.project_id = 1
Notice how to use alias for the table names to make the query clearer. Also then in operator is very handy. The use of double quotes with those identifiers is not necessary.
One way would be to use distinct:
SELECT distinct "formulation_batch".*
FROM "formulation_batch"
INNER JOIN "formulation_batch_component"
ON "formulation_batch"."id" = "formulation_batch_component"."formulationBatch_id"
WHERE "formulation_batch"."project_id" = 1
AND (("formulation_batch_component"."component_id" = 2
OR "formulation_batch_component"."component_id" = 1 ))
I know the question asks how to prevent duplicates with inner join but could use an IN clause in the predicate.
SELECT "formulation_batch".*
FROM "formulation_batch" fb
ON "formulation_batch"."id" = "formulation_batch_component"."formulationBatch_id"
WHERE "formulation_batch"."project_id" = 1
AND fb.id IN (SELECT "formulation_batch"."id"
FROM formulation_batch_component
WHERE (("formulation_batch_component"."component_id" = 2
OR "formulation_batch_component"."component_id" = 1 ))