如何使用条件联接到另一个表中的数据子集

时间:2019-06-18 15:47:26

标签: sql ssms

我有一个表格,其中包含来自不同研究的许多通胀因素,并希望将特定因素作为销售数据表格中的另一列引入。

我收到以下错误: 子查询返回的值超过1。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。

这是一个例子: dbo.Inflation

ID  Group   Year    Factor  
1   Dog    2010    1.00  
1   Dog    2011    1.01  
1   Dog    2012    1.02  
1   Cat    2010    2.00  
1   Cat    2011    2.10  
1   Cat    2012    2.20  
2   Dog    2010    1.05  
2   Dog    2011    1.04  
2   Dog    2012    1.03  
2   Cat    2010    2.50  
2   Cat    2011    2.40  
2   Cat    2012    2.30  

dbo.Sales

SalesID Year    DogSales    CatSales    TotalSales  
1      2010     50,000      25,000      75,000   
2      2010     10,000      15,000      25,000   
3      2011     75,000      50,000      125,000   
4      2012     12,000      10,000      22,000   
5      2012     40,000      15,000      55,000   
6      2012     40,000      30,000      70,000   

我想从我指定的ID中在“销售”表中同时为“狗”和“猫”返回通货膨胀因子。因此,如果我想将ID 1因子用作Dog因子,将ID 2因子用作Cat因子,结果将是这样的:

SalesID Year    DogSales    CatSales    TotalSales  Dog_     Cat_  
                                                    Factor  Factor  
1      2010     50,000      25,000      75,000      1.00     2.50   
2      2010     10,000      15,000      25,000      1.00     2.50   
3      2011     75,000      50,000      125,000     1.01     2.40   
4      2012     12,000      10,000      22,000      1.02     2.30   
5      2012     40,000      15,000      55,000      1.02     2.30   
6      2012     40,000      30,000      70,000      1.02     2.30   

我正在尝试使用带有内部联接的子查询来创建此新字段,从而不断出错。

Select distinct
Sales.SalesID
,Sales.Year
,Sales.DogSales
,Sales.CatSales
,Sales.TotalSales
,(SELECT Inflation.Factor from dbo.Inflation INNER JOIN dbo.Sales on Inflation.Year = Sales.Year  where Inflation.ID = 1 and Inflation.Group = 'Dog') as Dog_Factor
,(SELECT Inflation.Factor from dbo.Inflation INNER JOIN dbo.Sales on Inflation.Year = Sales.Year where Inflation.ID = 2 and Inflation.Group = 'Cat') as Cat_Factor

FROM dbo.Sales 

这给了我关于返回多个值的错误,尽管当我在where子句中使用那些相同的条件时,仅我想加入的一组因素才出现在通胀表的结果中。另外,当我将子查询更新为SELECT TOP 1而不是仅SELECT时,该表从正确的对应通货膨胀ID和组返回因子,但仅从2010年开始针对每一行返回因子,就好像它无法识别我的JOIN标准一样,请参见下文:

SalesID Year    DogSales    CatSales    TotalSales  Dog_     Cat_  
                                                    Factor  Factor  
1      2010     50,000      25,000      75,000      1.00     2.50   
2      2010     10,000      15,000      25,000      1.00     2.50   
3      2011     75,000      50,000      125,000     1.00     2.50   
4      2012     12,000      10,000      22,000      1.00     2.50   
5      2012     40,000      15,000      55,000      1.00     2.50   
6      2012     40,000      30,000      70,000      1.00     2.50   

我希望能够根据需要在ID和组之间进行切换,但是将年份作为我连接两个表的关键。

请注意,我还尝试在FROM语句之后的Year上重复执行join语句,但是由于太多结果,我也遇到了同样的错误。我也尝试了外部申请并得到了同样的东西。

在这里的任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:1)

另一种方法:

Select 
Sales.SalesID
,Sales.Year
,Sales.DogSales
,Sales.CatSales
,Sales.TotalSales
,MAX(case when Inflation.ID = 1 and Inflation.Group = 'Dog' then Inflation.Factor end) as Dog_Factor
,MAX(case when Inflation.ID = 2 and Inflation.Group = 'Cat'then Inflation.Factor end) as Cat_Factor   
FROM dbo.Sales 
LEFT JOIN dbo.Inflation ON Inflation.Year = Sales.Year
GROUP BY Sales.SalesID
,Sales.Year
,Sales.DogSales
,Sales.CatSales
,Sales.TotalSales

答案 1 :(得分:0)

您可以两次加入通胀表,一次用于狗,一次用于猫。

DEMO

SELECT
    s.*
  , id.factor AS [Dog_Factor]
  , ic.factor AS [Cat_Factor]
FROM dbo.sales s
JOIN dbo.inflation id  -- Dog
  ON id.year = s.year
  AND id.[group] = 'Dog'
  AND id.id = 1
JOIN dbo.inflation ic  -- Cat
  ON ic.year = s.year
  AND ic.[group] = 'Cat'
  AND ic.id = 2

答案 2 :(得分:0)

使用内联子查询时,通常需要通过WHERE子句将其与外部查询相关联:

Select distinct
 s.SalesID
,s.Year
,s.DogSales
,s.CatSales
,s.TotalSales
,(SELECT i.Factor from @Inflation AS i WHERE i.Year = s.Year AND i.ID = 1 and i.[Group] = 'Dog') as Dog_Factor
,(SELECT i.Factor from @Inflation AS i WHERE i.Year = s.Year AND i.ID = 2 and i.[Group] = 'Cat') as Cat_Factor
FROM @Sales AS s

不过,根据数据集的大小,使用两个JOIN返回Sales而不是相关子查询可能会获得更好的性能。

使用两次联接到Sales

SELECT
  s.SalesID,
  s.Year,
  s.DogSales,
  s.CatSales,
  s.TotalSales,
  d.Factor AS Dog_Factor,
  c.Factor AS Cat_Factor
FROM
  @Sales AS s
  LEFT JOIN
  (
    SELECT
      ID,
      [Year],
      Factor
    FROM 
      @Inflation 
    WHERE
      ID = 1
      AND
      [Group] = 'Dog'
  ) AS d
    ON d.Year = s.Year
  LEFT JOIN
  (
    SELECT
      ID,
      [Year],
      Factor
    FROM 
      @Inflation 
    WHERE
      ID = 2
      AND
      [Group] = 'Cat'
  ) AS c
    ON c.Year = s.Year

结果,无论哪种方式:

+---------+------+----------+----------+------------+------------+------------+
| SalesID | Year | DogSales | CatSales | TotalSales | Dog_Factor | Cat_Factor |
+---------+------+----------+----------+------------+------------+------------+
|       1 | 2010 |   50,000 |   25,000 |     75,000 |       1.00 |       2.50 |
|       2 | 2010 |   10,000 |   15,000 |     25,000 |       1.00 |       2.50 |
|       3 | 2011 |   75,000 |   50,000 |    125,000 |       1.01 |       2.40 |
|       4 | 2012 |   12,000 |   10,000 |     22,000 |       1.02 |       2.30 |
|       5 | 2012 |   40,000 |   15,000 |     55,000 |       1.02 |       2.30 |
|       6 | 2012 |   40,000 |   30,000 |     70,000 |       1.02 |       2.30 |
+---------+------+----------+----------+------------+------------+------------+