如何使用条件加入另一个 table 中的数据子集

How to join to subset of data in another table using criteria

我有一个 table,其中有许多来自不同研究的 inflation 因素,我想将特定因素作为销售数据 table 中的另一列引入。

我收到以下错误: 子查询 returned 超过 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 return Inflation 我的狗和猫的销售因素 table。因此,如果我想对狗因子使用 ID 1 因子,对猫因子使用 ID 2 因子,结果将是这样的:

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 

这给了我关于 return 多个值的错误,尽管我想加入的只有一组因素出现在 Inflation table 的结果中当我在 where 子句中使用这些相同的条件时。此外,当我将子查询更新为 SELECT TOP 1 而不仅仅是 SELECT 时,table returns 来自正确对应的 Inflation 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 和组之间切换,但将年份作为我连接两个 table 的密钥。

请注意,我也尝试在 FROM 语句之后重复加入 Year 的连接语句,但我得到了太多结果的相同错误。我也尝试了外部应用并得到了同样的东西。

如有任何帮助,我们将不胜感激!

您可以加​​入 inflation table 两次,一次是狗,一次是猫。

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

使用内联 sub-query 时,通常需要将其与外部查询相关联,这是通过 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 而不是相关的 sub-queries.[=17= 可能会获得更好的性能]

使用两个连接 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 |
+---------+------+----------+----------+------------+------------+------------+

另一种方法:

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