Select columns from multiple tables - sql

I have multiple tables with identical primary key fields but no other identical field. I want to select a collection of columns from all tables matching a specific primary key, something like so:
SELECT T1.a, T2.b, ..., TN.z FROM T1, T2, ..., TN WHERE T1.pk = "abc"

SELECT T1.a, T1.b, ..., TN.z
FROM T1 INNER JOIN T2 ON T1.pk = T2.pk
INNER JOIN T3 on T1.pk = T3.pk
...
INNER JOIN TN on T1.pk = TN.pk
AND TN.pk = "abc"
Or in a shorter form (thanks #Abelisto!).
SELECT T1.a, T1.b, ..., TN.z
FROM T1 JOIN T2 using(pk)
JOIN T3 using(pk)
...
JOIN TN using(pk)
WHERE TN.pk = "abc"

Related

Is it possible to share the same filter parameters (WHERE CLAUSE) with two more fields in SQL?

Consider below
SELECT * FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
WHERE
t1.A NOT IN ('111111','222222','33333')
AND
t2.B NOT IN ('111111','222222','33333')
Is there another way to use the same filter parameters for two different fields?
Something like that
SELECT * FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
WHERE (t1.A and t2.B) NOT IN ('111111','222222','33333')
Seems pretty simple, but I couldn't find anything in the docs.
You could use the array intersection operator (&&) to simulate that condition - create an array of the columns and an array of the values to test, and have a where clause that checks there's no intersection between them:
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
WHERE NOT ARRAY[t1.A, t2.B] && ARRAY['111111', '222222', '33333']
A CTE would be one possibility.
WITH cte
AS
(
SELECT c
FROM (VALUES ('111111'),
('222222'),
('33333')) v
(c)
)
SELECT *
FROM table1 t1
LEFT JOIN table2 t2
ON t1.id = t2.id
WHERE t1.a NOT IN (SELECT c
FROM cte)
AND t2.c NOT IN (SELECT c
FROM cte);

How do I look for non-matching values across 3 SQL tables?

I'm looking to do what I believe is a double-nested check across three tables, but have no idea how to do so.
I have Table1, Table2, and Table3.
All are tied by an ID and a "Longform" and "Shortform" in Table1:
I'm trying to find:
Entries whose IDs appear in Table2 that have the same Longform as those in Table3, but don't share the same Shortform.
This is about as far as I've gotten:
SELECT T2.Longform,T2.Shortform FROM(
SELECT Table1.Longform,Table1.Shortform,Table1.ID FROM OuterTable1.Table1
LEFT JOIN OuterTable2.Table2 on Table1.ID = Table2.ID)
WHERE Table2.ID IS NOT NULL) T2
;
I know I'm probably going to have to do another nested select, or a join, on Outertable3.Table3 but I'm not sure which... Or where...
Any help appreciated as always.
Try the following:
Select *
(
Select T1.*
from T2
inner join T1
on T1.ID = T2.ID
) as Tab
inner join
(
Select T1.*
from T3
inner join T1
on T1.ID = T3.ID
) as Tab2
on Tab.id = Tab2.id
and Tab.Longform = Tab2.Longform
and Tab.Shortform <> Tab2.Shortform
To get the longform join table1 to table2 or table3. Then use EXISTS to check in a subquery if the IDs of table1 are different but the longform is equal.
SELECT *
FROM table2 t21
INNER JOIN table1 t11
ON t11.id = t21.id
WHERE EXISTS (SELECT *
FROM table3 t32
INNER JOIN table1 t12
ON t12.id = t32.id
WHERE t12.id <> t11.id
AND t12.longform = t11.longform);
Assuming ID is unique in all three tables
Select t2.id,t2.shortform, t1.shortform AS shortformTab1, t2.longform
FROM table2 t2
JOIN table3 t3
ON t2.id = t3.id AND t2.longform = t3.longform
JOIN table1 t1
ON t2.id = t1.id AND t2.shortform != t1.shortform

select a columns not exist in another tables multiple columns in sql

I have two tables Tables1 with ID, name, and Table2 has ID1, ID2, and ID3, name1, name2, and name3.
I want to select table1.ID not exists in tables2: ID1, ID2, and ID3
select T1.ID,t1.name
from table1 t1
where not exists (
SELECT *
FROM table2 t2
where t1.ID=t2.ID1 or t1.ID=t2.ID2 or or t1.ID=t2.ID3 )
I get error message for this query
After a little research, I could find this. Basically, you can't have multiple columns for a subquery in a IN or a NOT IN condition in the WHERE clause. This is why your query is currently failing : Your subquery get all the columns from Table2.
From my understanding of your question, you want a select where the results would be the elements that are not existing in Table2.
To do this, you can simply use a LEFT OUTER JOIN. In SQL, I would left join on all three columns, but it seems like Hive does not support multiple conditions in JOIN statements, so you can use the following alternative :
SELECT T1.ID, T1.name
FROM Table1 T1
LEFT JOIN Table2 T2_1 ON T2_1.ID1 = T1.ID
LEFT JOIN Table2 T2_2 ON T2_2.ID2 = T1.ID
WHERE (T2_1.id IS NULL) AND -- the id of Table2 - T2_1
(T2_2.id IS NULL) -- the id of Table2 - T2_2
Just add as many LEFT JOIN and conditions in the WHERE clause as you have columns to check.
Here's a fiddle with this query concept (the data are not the same, but the concept is).
Join first by ID1, then resulted dataset join by ID2, then resulted dataset join by ID3:
select p2.ID, p2.name --pass3
from
(select p1.ID, p1.name --pass2
from
(SELECT T1.ID, T1.name --pass1
FROM Table1 T1
LEFT JOIN Table2 T2 ON T2.ID1 = T1.ID
where T2.ID1 is null --not in ID1
) p1 LEFT JOIN Table2 T2 ON T2.ID2 = p1.ID
where T2.ID1 is null --also not in ID2
) p2 LEFT JOIN Table2 T2 ON T2.ID3 = p2.ID
where T2.ID1 is null --also not in ID3
Joins on 2 and 3 steps will receive already reduced dataset from T1 and this solution may be good for big tables.
SELECT DISTINCT ID,NAME
FROM
(SELECT T1.ID, T1.name
FROM Table1 T1
LEFT OUTER JOIN Table2 T2 ON T2.ID1 = T1.ID
where T2.ID1 is null
union
SELECT T1.ID, T1.name
FROM Table1 T1
LEFT OUTER JOIN Table2 T2 ON T2.ID2 = T1.ID
where T2.ID2 is null
union
SELECT T1.ID, T1.name
FROM Table1 T1
LEFT OUTER JOIN Table2 T2 ON T2.ID3 = T1.ID
where T2.ID3 is null)JO

How do I get the results of one JOIN and THEN feed those into a separate join in T-SQL?

I'm trying to JOIN 2 tables ON a key like
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
Now, I have a 3rd table that has a Foreign Key with t2's id that I want to join... When I do
LEFT JOIN
Table3 t3 ON t3.t2id = --<-------------- This is where I'm lost
I don't know if I should do ON t3.t2id = t1.t2id OR ON t3.t2id = t2.id
What I need is the list of t2ids which are still in the picture after the first join. However, it seems as though if I specify either of the above, it will just pull ids from the original table before the first join?
To clarify one more time: I'm trying to essentially do a INNER JOIN of Table1 and Table2, get the resulting table, then get the t2ids of those results and feed them into a final join such that the final result contains all of Table3's rows as well as the data from the first join
You said: "final result contains all of Table3's rows as well as the data from the first join".
It means that you need
Table3 LEFT JOIN <previous results>
instead of
<previous results> LEFT JOIN Table3
The easiest way to write it is to use Common-Table Expressions:
WITH
CTE_InnerJoin
AS
(
SELECT column1, column2, t1.t2id
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
)
SELECT
CTE_InnerJoin.column1
,CTE_InnerJoin.column2
,Table3....
FROM
Table3
LEFT JOIN CTE_InnerJoin ON CTE_InnerJoin.t2id = Table3.t2id
;
It doesn't matter what column you include in the CTE: t1.t2id or t2.id, the values in them are the same, because they are inner-joined together.
JOINs already do exactly what you want. A JOIN isn't always between two tables. Frequently, it's between the results of previous joins.
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
LEFT JOIN
Table3 t3 ON t3.t2id = t2.id
At the point at which you're writing the final ON clause here, what you're joining is precisely the results of the previous INNER JOIN on the left and the table Table3 on the right. All of t1, t2 and t3 are in scope within the ON clause, but note that t1 and t2 are now both used as aliases into the same source of rows - the previous INNER JOIN.
As a further example, consider the "diamond join":
SELECT
*
FROM
t1
left join
t2
on
t1.a = t2.b
left join
t3
on
t1.c = t3.d
inner join
t4
on
t2.e = t4.f OR
t3.g = t4.h
This is a way of joining two tables (t1 and t4) based on two alternative joins. Note that in the final inner join, what is on the "left" is the result of already joining tables t1, t2 and t3.
Join the table having foreign key with
Try this....
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
LEFT join Table3 t3 ON t2.id=t3.t2id
Or Like this.
SELECT t12.column1 ,
t12.column2 ,
t3.*
FROM (
--- INNER JOIN of Table1 and Table2, get the resulting table,
SELECT t1.column1 ,
t2.column2 ,
t1.t2id --- or t2.id doesn't matter because its inner join
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
) T12
LEFT JOIN Table3 T3 ON t3.t2id = t1.t2id --- then get the t2ids of those results
--- and feed them into a final join
--- if you want to get all rows from Table3, Change LEFT JOIN Table3 T3 ON t3.t2id = T1.t2id
--- into RIGHT JOIN Table3 T3 ON t3.t2id = T1.t2id
try this
select t3.*, column1, column2
from
table1 t1 inner join table2 t2 on t1.t2id = t2.id
right outer join table3 t3 on t3.t2id = t2.id
equvalent to
select t3.*, column1, column2
from
table1 t1 inner join table2 t2 on t1.t2id = t2.id
right outer join table3 t3 on t3.t2id = t1.t2id
if you want all rows from table 3 and those matching rows from table1 inner joined to table2 then you can use this syntax:
select t3.*,
column1, column2
from table3 t3
left join table2 t2
inner join table1 t1
on t1.t2id = t2.id
on t3.t2id = t2.id

Sql Server : How to use an aggregate function like MAX in a WHERE clause

I want get the maximum value for this record. Please help me:
SELECT rest.field1
FROM mastertable AS m
INNER JOIN (
SELECT t1.field1 field1,
t2.field2
FROM table1 AS T1
INNER JOIN table2 AS t2 ON t2.field = t1.field
WHERE t1.field3=MAX(t1.field3)
-- ^^^^^^^^^^^^^^ Help me here.
) AS rest ON rest.field1 = m.field
As you've noticed, the WHERE clause doesn't allow you to use aggregates in it. That's what the HAVING clause is for.
HAVING t1.field3=MAX(t1.field3)
You could use a sub query...
WHERE t1.field3 = (SELECT MAX(st1.field3) FROM table1 AS st1)
But I would actually move this out of the where clause and into the join statement, as an AND for the ON clause.
The correct way to use max in the having clause is by performing a self join first:
select t1.a, t1.b, t1.c
from table1 t1
join table1 t1_max
on t1.id = t1_max.id
group by t1.a, t1.b, t1.c
having t1.date = max(t1_max.date)
The following is how you would join with a subquery:
select t1.a, t1.b, t1.c
from table1 t1
where t1.date = (select max(t1_max.date)
from table1 t1_max
where t1.id = t1_max.id)
Be sure to create a single dataset before using an aggregate when dealing with a multi-table join:
select t1.id, t1.date, t1.a, t1.b, t1.c
into #dataset
from table1 t1
join table2 t2
on t1.id = t2.id
join table2 t3
on t1.id = t3.id
select a, b, c
from #dataset d
join #dataset d_max
on d.id = d_max.id
having d.date = max(d_max.date)
group by a, b, c
Sub query version:
select t1.id, t1.date, t1.a, t1.b, t1.c
into #dataset
from table1 t1
join table2 t2
on t1.id = t2.id
join table2 t3
on t1.id = t3.id
select a, b, c
from #dataset d
where d.date = (select max(d_max.date)
from #dataset d_max
where d.id = d_max.id)
SELECT rest.field1
FROM mastertable as m
INNER JOIN table1 at t1 on t1.field1 = m.field
INNER JOIN table2 at t2 on t2.field = t1.field
WHERE t1.field3 = (SELECT MAX(field3) FROM table1)
yes you need to use a having clause after the Group by clause ,
as the where is just to filter the data on simple parameters ,
but group by followed by a Having statement is the idea to group the data and filter it on basis of some aggregate function......
But its still giving an error message in Query Builder. I am using SqlServerCe 2008.
SELECT Products_Master.ProductName, Order_Products.Quantity, Order_Details.TotalTax, Order_Products.Cost, Order_Details.Discount,
Order_Details.TotalPrice
FROM Order_Products INNER JOIN
Order_Details ON Order_Details.OrderID = Order_Products.OrderID INNER JOIN
Products_Master ON Products_Master.ProductCode = Order_Products.ProductCode
HAVING (Order_Details.OrderID = (SELECT MAX(OrderID) AS Expr1 FROM Order_Details AS mx1))
I replaced WHERE with HAVING as said by #powerlord. But still showing an error.
Error parsing the query. [Token line number = 1, Token line offset = 371, Token in error = SELECT]