Reputation: 315
Assume I have two tables which structure like below:
Table People:
---------------------------------------------------
| Pepole |ClothBrandId | ShoeBrandId | HatBrandId|
---------------------------------------------------
| Jo | 1 | 2 | 3 |
---------------------------------------------------
Table Brand:
-------------------------
| BrandId |BrandName |
-------------------------
| 1 | NBrand |
-------------------------
| 2 | ABrand |
-------------------------
| 3 | PBrand |
-------------------------
What I want is use T-SQL to generate a set as below:
---------------------------------------------------------
| Pepole |ClothBrandName | ShoeBrandName | HatBrandName|
---------------------------------------------------------
| Jo | NBrand | ABrand | PBrand |
---------------------------------------------------------
Currently, I think subquery in select statement can resolve this:
SELECT
People,
SELECT BrandName as ClothBrandName FROM Brand WHERE BrandId=ClothBrandId,
SELECT BrandName as ShoeBrandName FROM Brand WHERE BrandId=ShoeBrandId,
SELECT BrandName as HatBrandName FROM Brand WHERE BrandId=HatBrandId
FROM
People
But I don't think it a efficient solution. Another is use UNPIVOT then PIVOT. Which will be hard to read. Is there other appropriate ways for this?
Upvotes: 1
Views: 65
Reputation: 146499
Three simple joins will work
Select p.People,
c.BrandName ClothBrandName,
s.BrandName ShoeBrandName,
h.BrandName HatBrandName
From People p
Join Brand c On c.BrandId = p.ClothBrandId
Join Brand s On s.BrandId = p.ShoeBrandId
Join Brand h On h.BrandId = p.HatBrandId
but remember, the SQL Query Processor does not know from Joins vs Subqueries... The Parser (that reads your SQL and turns it into a cache plan) has to understand that, but inside the actual Query engine there are only three kinds of joins, and the query optimizer picks from these three based on the data statistics (and other factors). Whether you phrase your SQL as a join or as a correllated subquery does not control which of these three join types are used by the query engine. Quite often, if you do both versions, and they are logically equivalent, the show query plan will be identical.
Upvotes: 2
Reputation: 69759
I would go for three joins as opposed to subqueries:
SELECT People,
c.BrandName AS ClothBrandName,
s.BrandName AS ShoeBrandName,
h.BrandName AS HatBrandName
FROM People AS p
LEFT JOIN Brand AS c
ON c.BrandID = p.ClothBrandId
LEFT JOIN Brand AS s
ON s.BrandID = p.ShoeBrandId
LEFT JOIN Brand AS h
ON h.BrandID = p.HatBrandId;
If your fields in People
are not nullable then you can change your left joins to inner joins.
Upvotes: 1
Reputation: 25763
I would do 3 separate joins on Brand
SELECT
p.*,
cb.BrandName AS ClothBrandHane,
sb.BrandName AS ShoeBrandName,
hb.BrandName AS HatBrandName
FROM People p,
JOIN Brand cb ON cb.BrandID = p.ClothBrandID
JOIN Brand sb ON sb.BrandID = p.ShoeBrandID
JOIN Brand hb ON hb.BrandID = p.HatBrandID
Upvotes: 1
Reputation: 3732
Here is one alternative - joining Table Brand three times:
SELECT People, CB.BrandName, SB.BrandName, HB.BrandName
FROM People
LEFT JOIN Brand AS CB on BrandId = ClothBrandId
LEFT JOIN Brand AS SB on BrandId = ShoeBrandId
LEFT JOIN Brand AS HB on BrandId = HatBrandId
Change this to JOIN only if you're absolutely sure all three brands will appear in the tables.
Upvotes: 1
Reputation: 1269703
The proper query would look like:
SELECT p.*,
(SELECT BrandName FROM Brand b WHERE b.BrandId = p.ClothBrandId) as ClothBrandName,
(SELECT BrandName FROM Brand b WHERE b.BrandId = p.ShoeBrandId) as ShoeBrandName,
(SELECT BrandName FROM Brand b WHERE b.BrandId = p.HatBrandId) as HatBrandName
FROM People p;
I added table aliases. When working with more than one table, you should strive to use table aliases so someone reading the query (including yourself) knows where the columns are coming from.
This is as reasonable as doing left outer join
s, which is really the other option. Note that this assumes that Brand(BrandId)
is unique or a primary key. Otherwise, you might get multiple rows and an error in the query.
Upvotes: 1