SELECT from one table, based on join of two others - sql

I would like to
Select columns from table a
Where extension table a = extension in table b
And department in both table b and table c match
Based on that match that deptartment in table c should = yes
Select col1, col2, col3, col4, col5 from table a
Where col2 table a = col2 table b
And col3 in table b = col3 in table c
And col4 tabel c = yes
can anyone help.

Although your question is ambiguous have you tried:
SELECT A.COL1, A.COL2, A.COL3, A.COL4, A.COL5
FROM TABLE_A A
JOIN TABLE_B B
ON A.Extension = B.Extension
JOIN TABLE_C C
ON B.Department = C.Department
AND C.Department = 'yes'

You can do this in different ways. As following:
Way 1
SELECT col1, col2, col3, col4, col5
FROM tableA
JOIN tableB ON tableA.col2 = tableB.col2
JOIN tableC ON tableB.col3 = tableC.col3 AND tableC.col4 = 'yes'
Way 2
SELECT col1, col2, col3, col4, col5
FROM tableA
JOIN tableB ON tableA.col2 = tableB.col2
JOIN tableC ON tableB.col3 = tableC.col3
WHERE tableC.col4 = 'yes'
Way 3
SELECT *
INTO #col4yesTable
FROM tableC
Where col4 = 'yes'
SELECT tableA.col1, tableA.col2, tableA.col3, tableA.col4, tableA.col5
FROM #col4yesTable
JOIN tableB ON #col4yesTable.col3 = tableB.col3
JOIN tableB ON tableA.col2 = tableB.col2
Depends on your need you can use one of them. The last one, creates a temporary table to store all tableC objects that has col4 = 'yes'

Related

Show Rows That Are Different Between Two Tables - MS Access

I have been working on trying to convert the following SQL-Server code to achieve a similar result in MS Access.
WITH TableA(Col1, Col2, Col3)
AS (SELECT 'Dog',1,1 UNION ALL
SELECT 'Cat',27,86 UNION ALL
SELECT 'Cat',128,92),
TableB(Col1, Col2, Col3)
AS (SELECT 'Dog',1,1 UNION ALL
SELECT 'Cat',27,105 UNION ALL
SELECT 'Lizard',83,NULL)
SELECT CA.*
FROM TableA A
FULL OUTER JOIN TableB B
ON A.Col1 = B.Col1
AND A.Col2 = B.Col2
/*Unpivot the joined rows*/
CROSS APPLY (SELECT 'TableA' AS what, A.* UNION ALL
SELECT 'TableB' AS what, B.*) AS CA
/*Exclude identical rows*/
WHERE EXISTS (SELECT A.*
EXCEPT
SELECT B.*)
/*Discard NULL extended row*/
AND CA.Col1 IS NOT NULL
ORDER BY CA.Col1, CA.Col2
Gives
what Col1 Col2 Col3
------ ------ ----------- -----------
TableA Cat 27 86
TableB Cat 27 105
TableA Cat 128 92
TableB Lizard 83 NULL
So far I have been able to convert get replication of the FULL OUTER JOIN using the following code, but I have been unable to replicate unpivoting the joint rows (CROSS APPLY).
(SELECT *
FROM TableA AA
INNER JOIN TableB BB ON AA.Col1 = BB.Col1
UNION ALL
SELECT *
FROM TableA AA
LEFT JOIN TableB BB ON AA.Col1 = BB.Col1
WHERE BB.[IP Number] IS NULL
UNION ALL
SELECT *
FROM TableA AA
RIGHT JOIN TableB BB ON AA.Col1 = BB.Col1
WHERE AA.Col1 IS NULL
)
I could use some help achieving the same result in a MS-Access query.
From what I can gather, you have two tables that have unique rows. You want to return rows that are present in one table but not the other.
I would suggest aggregation and HAVING for this -- in either database:
SELECT col1, col2, col3
FROM ((SELECT col1, col2, col3 FROM TableA) UNION ALL
(SELECT col1, col2, col3 FROM TableB)
) as ab
GROUP BY col1, col2, col3
HAVING COUNT(*) = 1;
Or alternatively, two NOT EXISTS clauses:
SELECT a.*
FROM TableA as a
WHERE NOT EXISTS (SELECT 1
FROM TableB as b
WHERE (a.col1 = b.col1 OR a.col1 IS NULL AND b.col1 IS NULL) AND
(a.col2 = b.col2 OR a.col2 IS NULL AND b.col2 IS NULL) AND
(a.col3 = b.col3 OR a.col3 IS NULL AND b.col3 IS NULL)
)
UNION ALL
SELECT b.*
FROM TableB as b
WHERE NOT EXISTS (SELECT 1
FROM TableA as a
WHERE (a.col1 = b.col1 OR a.col1 IS NULL AND b.col1 IS NULL) AND
(a.col2 = b.col2 OR a.col2 IS NULL AND b.col2 IS NULL) AND
(a.col3 = b.col3 OR a.col3 IS NULL AND b.col3 IS NULL)
);
Here is a db<>fiddle that uses SQL Server, but the syntax should be basically the same in MS Access.

Is it good approach to Find Maximums from nested SQL query and then use that maximum value again in same query

Is it a good approach to Find Maximums from nested SQL query and then use that maximum value again in the same query.
For example:
Select Col1, Col2, Col3, Col2/Col3 AS Col4, CASE Alot of statements END Col5
from Table A inner join Table B on A.Id = B.Id
Inner Join Table C on B.Id = C.Id
Inner Join Table D on C.Id = D.Id
Now I need to find Maximum integer from Col5 and then later use that Max Value to divide Col4 value.
I also need to display col1 and col2 along with results.
Expected result:
Col1, Col2, (Col4/MaxValue of Col5)
Could anybody guide me what's the best solution in this case?
If those are the only results you need, then no subquery/CTE is needed:
Select Col1, Col2,
( (Col2 / Col3) /
max(case Alot of statements end) over ()
) as ratio
from Table A inner join
Table B
on A.Id = B.Id Inner Join
Table C
on B.Id = C.Id Inner Join
Table D
on C.Id = D.Id;
Tim's answer is definitely a good answer if you need col5 more than once in the final result set.
You can use a common table expression:
WITH cte AS (
SELECT Col1, Col2, Col3, Col2/Col3 AS Col4,
CASE Alot of statments END Col5
FROM TableA A
INNER JOIN TableB B
ON A.Id = B.Id
INNER JOIN TableC C
ON B.Id = C.Id
INNER JOIN TableD D
ON C.Id = D.Id
)
SELECT t.Col1, t.Col2,
t.Col4 / MAX(t.Col5) OVER ()
FROM cte t

Optimize SQL statement

I have a requirement to update a column in table A if the count of records in table B grouped by 3 columns (matching between A and B) is less than 7. I have written below query, but it is running long. Please suggest any optimal query or tune this.
update /*+ parallel(A) */ A set A.col4=0
where exists
(select 1
from B
where A.col1=B.col1 and A.col2=B.col2
and A.col3=B.col3
group by col1,col2,col3
having count(*) < 7)
Try this,
MERGE INTO A
USING (
SELECT col1, col2, col3
FROM B
GROUP BY col1, col2, col3
HAVING COUNT(*) > 7
) b ON (A.col1 = b.col1 AND A.col2=b.col2 AND A.col3= b.col3)
WHEN MATCHED THEN UPDATE
SET A.col4 = 0;
View it on SQL Fiddle: http://www.sqlfiddle.com/#!4/dcdf1/17
Let me know if it worked or not!
My first suggestion is to create an index on B: B(col1, col2, col3).
The next attempt would be to switch this to a join:
update A
set col4 = 0
from (select col1, col2, col3
from B
group by col1, col2, col3
having count(*) < 7
) B
where A.col1 = B.col1 and A.col2 = B.col2
and A.col3 = B.col3 ;

Combine multiple varchar rows into one

Col1 Col2 Col3 Col4 Col5 Col6 Col7 Col8
CH-0000001 IN-0000001 IN-0000001 ALL NULL NULL NULL NULL
CH-0000001 PR-0000001 NULL NULL PR-0000001 ALL NULL NULL
CH-0000001 PU-0000001 NULL NULL NULL NULL PU-0000001 ALL
Hey guys I am trying to squish all this information into a single row based on a key Col1. I have seen a trick using MAX and SUM but it only seems to work for numbers. Here is the desired result.
Col1 Col3 Col4 Col5 Col6 Col7 Col8
CH-0000001 IN-0000001 ALL PR-0000001 ALL PU-0000001 ALL
Also, this problem arose from LEFT JOINing 3 tables from one master table of keys. Let me know if my approach to getting to this state is the wrong way to approach this problem. Here is the query
SELECT * FROM GCL_Blackboard A
LEFT JOIN GCL_Investors B ON A.Adjective_ID = B.Investor_ID
LEFT JOIN GCL_Loan_Programs C ON A.Adjective_ID = C.Program_ID
LEFT JOIN GCL_Loan_Purposes D ON A.Adjective_ID = D.Purpose_ID
I think this is the logic you want:
SELECT a.col1,
max(coalesce(b.col2, c.col2, d.col2)) as col2,
max(coalesce(b.col3, c.col3, d.col3)) as col3,
max(coalesce(b.col4, c.col4, d.col4)) as col4,
max(coalesce(b.col5, c.col5, d.col5)) as col5,
max(coalesce(b.col6, c.col6, d.col6)) as col6,
max(coalesce(b.col7, c.col7, d.col7)) as col7,
max(coalesce(b.col8, c.col8, d.col8)) as col8
FROM GCL_Blackboard A LEFT JOIN
GCL_Investors B
ON A.Adjective_ID = B.Investor_ID LEFT JOIN
GCL_Loan_Programs C
ON A.Adjective_ID = C.Program_ID LEFT JOIN
GCL_Loan_Purposes D
ON A.Adjective_ID = D.Purpose_ID
GROUP BY a.col1;
The query is a bit of a guess, because I don't know where the columns are coming from.
You can do:
SELECT A.Col1,
MIN(Col3) Col3,
MIN(Col4) Col4 ....
FROM GCL_Blackboard A
LEFT JOIN GCL_Investors B ON A.Adjective_ID = B.Investor_ID
LEFT JOIN GCL_Loan_Programs C ON A.Adjective_ID = C.Program_ID
LEFT JOIN GCL_Loan_Purposes D ON A.Adjective_ID = D.Purpose_ID
GROUP BY A.Col1

Get rows from the first tables even if they don't exist in the last table in a join without left joining

I'm working with an Oracle database, and i have a query where i have to perform a join of 7 different tables.
Now, my problem is, i need to get rows that fulfill the requirements of the join (obviously) but even if they don't match the conditions of the last join i need to get the rows from the first 6 tables.
I can't do a left outer join, so what alternatives do i have?
The code looks something like this:
with
tmp as (select col1, col2, col3, col4, row_number() over (partition by col1 order by col2 desc) rn
from
(select /*+ MATERIALIZE */
col1, col2, col3, col4
from
table1
where
col3 in ('A','R','F') and
somedate >= sysdate-720 and
col5 is null
and col1<> '0000000000'))
select /*+ use_hash(a,b,c,d,e,f,g,h) */
b.col5,
a.col1,
d.col6,
e.col7,
c.col8 ,
(CASE when f.col9= 'B' then 'Foo' else 'Bar' END) as "col9",
a.col2,
a.col3,
h.col10
from tmp a
join table2 b on
a.col1= b.col1 and
a.col4=b.col4 and
b.col11='P' and
(b.otherDate>= sysdate OR b.otherDate is null) and
b.col5 is null
join table3 c on
b.col12 = c.col12 and
(c.otherDate is null or b.otherDate >= sysdate) and
c.col5 is null
join table4 d on
a.col1= d.col1 and
d.col13 in ('R','A','F') and
d.col5 is null
join table5 e on
e.col1=b.col1 and
e.col14=d.col14 and
d.col6=e.col6 and
d.col15 = e.col15 and
e.col5 is null
join table6 f on
f.col4= a.col4 and
f.col5 is null
join table7 g on
g.col16= case when f.col15 is null then null else f.col15 end
and g.col5is null
and (g.otherDate is null or g.otherDate >= sysdate)
join table8 h on
h.col17= g.col17
and (h.otherDate >= sysdate or h.otherDate is null)
and h.col5 is null
and a.rn=1;
I'm not going to attempt to work with your actual query, but in principle you could change:
select tab1.col1, tab2.col2, tab3.col3
from tab1
join tab2 on tab2.fk = tab1.pk
join tab3 on tab3.fk = tab2.pk
into:
select tab1.col1, tab2.col2, tab3.col3
from tab1
join tab2 on tab2.fk = tab1.pk
left join tab3 on tab3.fk = tab2.pk
which you could replace (in your out-joins-not-allowed world) with:
with tmp as (
select tab1.col1, tab2.col2, tab3.pk
from tab1
join tab2 on tab2.fk = tab1.pk
)
select tmp.col1, tmp.col2, tab3.col3
from tmp
join tab3 on tab3.fk = tmp.pk
union all
select tmp.col1, tmp.col2, null as col3
from tmp
where not exists (
select null from tab3
where tab3.fk = tmp.pk
)
Which is quite ugly - I've minimised the repetition with a CTE, but even so not nice - and is likely to not perform as well as the outer join would.
Of course, without knowing why you can't use an outer join, I don't know if there are other restrictions that would make this approach unacceptable as well...