必须有更好的方法来编写此查询?

时间:2011-08-18 16:38:28

标签: sql-server sql-server-2005 tsql

这个查询有效,但看起来非常低效。必须有更好的方法吗?

我要做的是根据公司所在的区域从MarketRates表中选择4个不同的列。只有4个区域,在Company表中存储为整数1-4。因此,例如,如果区域为“1”,那么我想选择4个南加州列(列名称为SCA *),但如果区域为“2”,那么我想选择4个Norhtern California列(列名是NCA *)等。

我知道表格应该以不同的方式构建,但这是我必须处理的。

MarketRates表包含这些列(SCA =南加州,NCA =北加州,SNV =南内华达州,NAZ =北亚利桑那州:

  • EndingDate - date
  • SCA_MRK - 十进制(8,2)
  • SCA_RATE - decimal(8,2)
  • SCA_COMP - 小数(8,2)
  • SCA_NEG - 小数(8,2)
  • NCA_MRK - 小数(8,2)
  • NCA_RATE - decimal(8,2)
  • NCA_COMP - 小数(8,2)
  • NCA_NEG - 小数(8,2)
  • SNV_MRK - 十进制(8,2)
  • SNV_RATE - decimal(8,2)
  • SNV_COMP - decimal(8,2)
  • SNV_NEG - 十进制(8,2)
  • NAZ_MRK - 十进制(8,2)
  • NAZ_RATE - 小数(8,2)
  • NAZ_COMP - 小数(8,2)
  • NAZ_NEG - 小数(8,2)

这是我正在使用的当前查询:

Select CompanyName
  , case TerritoryNumber 
    when 1 then (Select top 1 coalesce(SCA_MRK,0) From MarketRates Order by EndingDate desc) 
    when 2 then (Select top 1 coalesce(NCA_MRK,0) From MarketRates Order by EndingDate desc) 
    when 3 then (Select top 1 coalesce(SNV_MRK,0) From MarketRates Order by EndingDate desc) 
    when 4 then (Select top 1 coalesce(NAZ_MRK,0) From MarketRates Order by EndingDate desc) 
  end AS MRK
  , case TerritoryNumber 
    when 1 then (Select top 1 coalesce(SCA_RATE,0) From MarketRates Order by EndingDate desc) 
    when 2 then (Select top 1 coalesce(NCA_RATE,0) From MarketRates Order by EndingDate desc) 
    when 3 then (Select top 1 coalesce(SNV_RATE,0) From MarketRates Order by EndingDate desc) 
    when 4 then (Select top 1 coalesce(NAZ_RATE,0) From MarketRates Order by EndingDate desc) 
  end AS RATE
  , case TerritoryNumber 
    when 1 then (Select top 1 coalesce(SCA_COMP,0) From MarketRates Order by EndingDate desc) 
    when 2 then (Select top 1 coalesce(NCA_COMP,0) From MarketRates Order by EndingDate desc) 
    when 3 then (Select top 1 coalesce(SNV_COMP,0) From MarketRates Order by EndingDate desc) 
    when 4 then (Select top 1 coalesce(NAZ_COMP,0) From MarketRates Order by EndingDate desc) 
  end AS COMP
  , case TerritoryNumber 
    when 1 then (Select top 1 coalesce(SCA_NEG,0) From MarketRates Order by EndingDate desc) 
    when 2 then (Select top 1 coalesce(NCA_NEG,0) From MarketRates Order by EndingDate desc) 
    when 3 then (Select top 1 coalesce(SNV_NEG,0) From MarketRates Order by EndingDate desc) 
    when 4 then (Select top 1 coalesce(NAZ_NEG,0) From MarketRates Order by EndingDate desc) 
  end AS NEG
from Company 
where CompanyID = 'THISID'

3 个答案:

答案 0 :(得分:2)

您只需从MarketRates中选择一行,因为您每次都引用同一行。在子查询中选择它并加入它,您可以在整个查询中引用它。我重写了MRK的样子,其他列也有类似的语法/逻辑。

Select CompanyName
  , case TerritoryNumber 
    when 1 then coalesce(SCA_MRK,0)
    when 2 then coalesce(NCA_MRK,0)
    when 3 then coalesce(SNV_MRK,0)
    when 4 then coalesce(NAZ_MRK,0)
  end AS MRK
  , ...etc
from Company 
cross join (select top 1 * from MarketRates order by EndingDate desc) MarketRates
where CompanyID = 'THISID'

答案 1 :(得分:0)

DECLARE 
    @TerritoryID INT,
    @CompanyName VARCHAR(32);

SELECT 
    @CompanyName = CompanyName,
    @TerritoryID = TerritoryNumber 
FROM Company 
WHERE CompanyID = 'THISID';

SELECT TOP 1
    CompanyName = @CompanyName,
    MRK = CASE @TerritoryID
        WHEN 1 THEN SCA_MRK
        WHEN 2 THEN NCA_MRK
        WHEN 3 THEN SNV_MRK
        WHEN 4 THEN NAZ_MRK END,
    RATE = CASE @TerritoryID
        WHEN 1 THEN SCA_RATE
        WHEN 2 THEN NCA_RATE
        WHEN 3 THEN SNV_RATE
        WHEN 4 THEN NAZ_RATE END,
    COMP = CASE @TerritoryID
        WHEN 1 THEN SCA_COMP
        WHEN 2 THEN NCA_COMP
        WHEN 3 THEN SNV_COMP
        WHEN 4 THEN NAZ_COMP END,
    NEG = CASE @TerritoryID
        WHEN 1 THEN SCA_NEG
        WHEN 2 THEN NCA_NEG
        WHEN 3 THEN SNV_NEG
        WHEN 4 THEN NAZ_NEG END
FROM MarketRates
ORDER BY EndingDate DESC;

答案 2 :(得分:0)

您可以使用一个案例块保持清洁和快速。 (您可以替换变量类型以匹配列数据类型。) 检查下面创建的动态SQL。

DECLARE @CompanyName varchar(50), @TerritoryNum int, @ColumnType varchar(10), @SQL VARCHAR(1000);
SELECT @CompanyName = CompanyName ,@TerritoryNum = TerritoryNumber 
    FROM Company WHERE CompanyID = 'THISID'
SET @ColumnType = CASE @TerritoryNum WHEN 1 THEN 'SCA_'
                                    WHEN 2 THEN 'NCA_'
                                    WHEN 3 THEN 'SNV_'
                                    WHEN 4 THEN 'NAZ_'
                                    END

SET @SQL = '
SELECT 
    ''' + @CompanyName + ''' AS CompanyName,
    COALESCE(' + @ColumnType + 'MRK,0) AS MRK,
    COALESCE(' + @ColumnType + 'RATE,0) AS RATE,
    COALESCE(' + @ColumnType + 'COMP,0) AS COMP,
    COALESCE(' + @ColumnType + 'NEG,0) AS NEG
FROM MarketRates
'
PRINT @SQL
EXEC(@SQL)

动态查询(可以从Print看到)就像下面那样简单,其中Company表在CompanyName列中有'Comp',在TerritoryNumber列中有2。尝试将其更改为Company表中的其他数字,并在动态查询中显示相应的MarketRates列。

SELECT 
    'Comp' AS CompanyName,
    COALESCE(NCA_MRK,0) AS MRK,
    COALESCE(NCA_RATE,0) AS RATE,
    COALESCE(NCA_COMP,0) AS COMP,
    COALESCE(NCA_NEG,0) AS NEG
FROM MarketRates