How to optimize multiple subqueries that are running for lookup tables - sql

I have two looK up tables, and need is to fetch value by correlating the both tables.
As of now I am doing this with multiple sub queries and trying to find a easiest way.
SELECT
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'A') AND T1.ID = 'AA')as A,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'B') AND T1.ID = 'BB')AS B,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'C') AND T1.ID = 'CC')AS C,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'D') AND T1.ID = 'DD')AS D,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'E') AND T1.ID = 'EE')AS E,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'F') AND T1.ID = 'FF')AS F
FROM MYTABLE;

I assume you need something like this.
SELECT MAX ( CASE WHEN T1.ID = 'AA' AND T2.ID = 'A' THEN TYPE_NAME END ) as A,
MAX ( CASE WHEN T1.ID = 'BB' AND T2.ID = 'B' THEN TYPE_NAME END ) as B,
MAX ( CASE WHEN T1.ID = 'CC' AND T2.ID = 'C' THEN TYPE_NAME END ) as C,
..
FROM T1 t1
INNER JOIN T2 t2
ON t1.FK_T2 = t2.PK

I'll try something like:
SELECT
T1.TYPE_NAME,
T1.ID
FROM T1 t1
INNER JOIN T2 t2
ON t1.FK_T2 = t2.PK
WHERE
T1.ID||T1.ID = T2.ID

You could try rephrasing these queries as a single query consisting of a join between the two tables:
SELECT
T1.TYPE_NAME,
T1.ID
FROM T1 t1
INNER JOIN T2 t2
ON t1.FK_T2 = t2.PK
WHERE
(T1.ID = 'AA' AND T2.ID = 'A') OR
(T1.ID = 'BB' AND T2.ID = 'B') OR
(T1.ID = 'CC' AND T2.ID = 'C') OR
(T1.ID = 'DD' AND T2.ID = 'D') OR
(T1.ID = 'EE' AND T2.ID = 'E') OR
(T1.ID = 'FF' AND T2.ID = 'F');
You can keep track of to which subquery each returned record corresponds by checking the value of the ID column in the first table. This would serve as a marker for the source subquery.

Related

SQL three table joins using two ids and another column

I have three tables
t1 t2 t3
I want to select data from only two of the tables but need the ids and columns from other tables for reference.
How to select data from t3 and t2
WHERE t1.id = t2.id = t3.id
AND t1.fid = t2.fid = t3.fid
AND t1.type = 'abc'
id column will be the same value for all tables. fid column will have incremental fid's but need the ones where t1.type = 'abc' also
Would this work?
select data
from t3
select data
from t2
join on t1.id = t2.id and t2.id = t3.id
join on t1.fid = t2.fid and t2.fid = t3.fid and t1.type = 'abc'
where id = 1
Generally, this kind of problem can be solved using EXISTS as follows:
select data
from t2
join t1 on t1.id = t2.id and t1.fid = t2.fid
where exists (select 1 from t3 where t2.id = t3.id and t2.fid = t3.fid)
and t1.type = 'abc'
and t1.id = 1
You could try something like this:
select columns_that_you_want
from t1 x
inner join t2 y on x.id = y.id
inner join t3 z on y.id = z.id
where x.type = 'abc'
;
This will join the three tables, and filter just the type 'abc' that you want from table t1. Also you can add more filter on the where clause in case you need to filter more the result.

Pivot and kind of cross-join at same time

I have two tables:
I'm trying to construct a table that returns:
Where:
T3.VALUE_0M column is equal to T2.VALUE if:
T2.OLD_DATE = T1.REF_DATE and T2.ID = T1.ID
or:
T3.VALUE_0M is NULL if there is no T2.OLD_DATE = T1.REF_DATE.
T3.VALUE_1M column is equal to T2.VALUE if: T1.OLD_DATE =
ADD_MONTHS(T1.REF_DATE,-1) and T2.ID = T1.ID
or:
T3.VALUE_1M is NULL if there is no T2.OLD_DATE =
ADD_MONTHS(T1.REF_DATE,-1).
T3.VALUE_2M column is equal to T2.VALUE if:
T1.OLD_DATE = ADD_MONTHS(T1.REF_DATE,-2) and T2.ID = T1.ID
or:
T3.VALUE_2M is NULL if there is no T2.OLD_DATE = ADD_MONTHS(T1.REF_DATE,-2).
and so on.
My challenge is: if there are more than one value for the same T2.ID and T2.OLD_DATE, i want to show both of them in different rows, but crossing with the other VALUE columns.
I've tried to use cross join, but the result was not the desired:
Could be someone so kind and help me with this stuff?
Thank you very much!
As much as I understand, the resulting query would be such like the below one :
SELECT t1.ID, t2.ref_date,
(case when ( T1.OLD_DATE = T2.REF_DATE and T2.ID = T1.ID )
then t1.value end) value_0m,
(case when ( T1.OLD_DATE = ADD_MONTHS(T2.REF_DATE,-1) and T2.ID = T1.ID )
then t1.value end) value_1m,
(case when ( T1.OLD_DATE = ADD_MONTHS(T2.REF_DATE,-2) and T2.ID = T1.ID )
then t1.value end) value_2m,
(case when ( T1.OLD_DATE = ADD_MONTHS(T2.REF_DATE,-3) and T2.ID = T1.ID )
then t1.value
end) value_3m
FROM T1 CROSS JOIN T2;
SQL Fiddle Demo

Case( select) when then

The query is compiled correctly. Prompt how to make correctly. You need to get three variables and check them out. Depending on the selected test date.
after when is not written correctly
select sum(t.sum),t3.cost, t.status
from Credit t inner join cost t3 on t.code= t3.code1
where t.id='1' and
t.date >= case (SELECT t1.mark1, t1.mark2, t2.mark3
FROM marks t1 INNER JOIN marksagain t2 ON (t1.id = t2.id)
WHERE t1.id = t.id)
when (0,0,6) then (INTNX('month',date(),6,'same'))
else(INTNX('month',date(),3,'same')) end
group by t.sum, t3.cost, t.status;`
Try out this:
select sum(t.sum),t3.cost, t.status
from Credit t inner join cost t3 on t.code= t3.code1
where t.id='1' and t.date >=
case when (SELECT t1.mark1 FROM marks t1 INNER JOIN marksagain t2 ON (t1.id = t2.id) WHERE t1.id = t.id) = 0
AND (SELECT t1.mark2 FROM marks t1 INNER JOIN marksagain t2 ON (t1.id = t2.id) WHERE t1.id = t.id) = 0
AND (SELECT t2.mark3 FROM marks t1 INNER JOIN marksagain t2 ON (t1.id = t2.id) WHERE t1.id = t.id) = 6
then (INTNX('month',date(),6,'same')) else(INTNX('month',date(),3,'same'))
end
group by t.sum, t3.cost, t.status;

SQL: select from t1 all rows for which there's no corresponding in t2

Let's say I have a table t1 with only one column: id, and I have a table t2 with two columns: id and Memo. I need to select those id from t1, for which there is NO row in t2 that satisfies both of the following two conditions t1.id = t2.id and t2.Memo = 'myText'. How can I do that? I have tried using join, but that selects row that do satisfy some conditions, whereas I need the opposite.
SELECT *
FROM t1
WHERE NOT EXISTS (SELECT 1
FROM t2
WHERE t2.id = t1.id
AND t2.Memo = 'myText')
One way to do it is using LEFT JOIN:
select id
from t1
left join t2
on t1.id = t2.id and t2.Memo = 'myText'
where t2.id is null
I'm not good in understanding your question:
You mean those t1.id EXISTS in t2 BUT the corresponding t2.Memo <> 'myText'?
SELECT t1.id FROM t1 JOIN t2
ON t1.id = t2.id
HAVING t1.id NOT IN (SELECT id FROM t2 WHERE Memo = 'myText');
Or all t1.id either NOT EXISTS in t2 or EXISTS but Memo <> 'myText'?
SELECT id FROM t1 WHERE id NOT IN (SELECT id FROM t2 WHERE Memo = 'myText');

PostgreSQL LEFT JOIN not working properly

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'