Select语句中的SubQuery是否适合此问题?

时间:2014-05-29 14:31:43

标签: sql subquery

假设我有两个表格,结构如下:

表人:

---------------------------------------------------
| Pepole |ClothBrandId  | ShoeBrandId | HatBrandId|
---------------------------------------------------
| Jo     | 1            | 2           | 3         |
---------------------------------------------------

表品牌:

 -------------------------
 | BrandId |BrandName    |
 -------------------------
 | 1       | NBrand      |
 -------------------------
 | 2       | ABrand      |
 -------------------------
 | 3       | PBrand      |
 -------------------------

我想要的是使用T-SQL生成如下集:

    ---------------------------------------------------------
    | Pepole |ClothBrandName  | ShoeBrandName | HatBrandName|
    ---------------------------------------------------------
    | Jo     | NBrand         | ABrand        | PBrand      |
    ---------------------------------------------------------

目前,我认为select语句中的子查询可以解决这个问题:

 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

但我认为这不是一个有效的解决方案。 另一个是使用UNPIVOT然后是PIVOT。这将很难读。 还有其他适当的方法吗?

5 个答案:

答案 0 :(得分:2)

三个简单的连接将起作用

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

但请记住,SQL查询处理器不知道来自联接与子查询...解析器(读取您的SQL并将其转换为缓存计划)必须了解这一点,但在实际的查询引擎中只有三个各种连接,查询优化器根据数据统计(和其他因素)从这三种连接中选取。无论是将SQL表示为连接还是作为相关子查询,都不能控制查询引擎使用这三种连接类型中的哪一种。通常,如果您同时执行这两个版本,并且它们在逻辑上是等效的,那么show query plan将是相同的。

  1. Nested Loops
  2. Hash Join
  3. Merge Join

答案 1 :(得分:1)

正确的查询如下:

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;

我添加了表别名。当使用多个表时,您应该努力使用表别名,以便阅读查询的人(包括您自己)知道列的来源。

这与执行left outer join一样合理,这实际上是另一种选择。请注意,这假设Brand(BrandId)是唯一的或主键。否则,您可能会在查询中获得多行和错误。

答案 2 :(得分:1)

我会选择三个连接而不是子查询:

 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;

<强> Example on SQL Fiddle

如果People中的字段不可为空,则可以将左连接更改为内连接。

答案 3 :(得分:1)

这是另一种选择 - 三次加入Table Brand:

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

只有在您完全确定所有三个品牌都会出现在表格中时才将其更改为“加入”。

答案 4 :(得分:1)

我会在Brand

上进行3次单独的联接
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