使用字段的MAX来选择记录返回表中的MAX忽略条件

时间:2013-04-12 07:51:31

标签: sql-server-2008 tsql stored-procedures cursor max

我正在为报告执行存储过程,而我正在尝试仅获取具有确定字段(累积量)的最高值的那些记录,事情是我似乎无法找到解决方案这个,我提出的唯一解决方案是使用一个额外的条件,问题是每个月(期间)字段更改而不是所有记录都更新但我需要检索它们...(如果是资产在那里折旧不再是该表中与该资产相关的记录)

如果这令人困惑,我很抱歉,我会尽力解释

报告需要为每个供应商注册一份供应资产清单,其描述,当前位置,价格以及需要从资产中折旧多少钱。

所以,我正在做的是首先获取供应商列表,然后获取与位置相关联的资产列表(使用游标)然后我尝试计算需要折旧的资金,有一个名为'的表DEPRECIACIONES'存储资产,期间以及每个期间从该资产折旧的金额以及尚未完全折旧的每项资产。当我尝试计算资产折旧的MAX金额然后选择具有该MAX金额的该项的行时,问题就来了,我确定我做错了,我的TSQL和一般数据库知识不是好,我正在努力学习。

我上传了错误输出的架构,表格和存储过程:

http://sqlfiddle.com/#!3/78c32

正确的输出应该是这样的:

Proveedor | Activo | Descripcion | Ubicacion Actual | Costo Adquisicion | Saldo sin depreciar | Periodo

Supplier | Asset | Description | Current Location | Cost | Money to be depreciated | Period
-------------------------------------------------------------------------------------------
Monse    |ActivoT|  texthere   |       1114       |2034.50|    RANDOM NUMBER HERE  |RandomP
Monse    |cesart |  texthere   |       4453       |4553.50|    RANDOM NUMBER HERE  |RandomP
nowlast  | activ |  texthere   |       4453       |1234.65|    RANDOM NUMBER HERE  |RandomP
nowlast  |augusto|  texthere   |       4450       |4553.50|    RANDOM NUMBER HERE  |RandomP
Sara     |Activo |  texthere   |       1206       |746.65 |    RANDOM NUMBER HERE  |RandomP

我真的很感激地告诉我我做错了什么(可能很多)以及如何解决它,谢谢你提前。

2 个答案:

答案 0 :(得分:1)

通过SqlFiddle提供完整信息的良好技能。

我没有完整的答案,但这可能有所帮助。

首先,抛弃光标 - 很难调试,可能会慢。重构为SELECT语句。这是我的尝试,它应该在逻辑上等同于您的代码:

SELECT 
  p.Proveedor,
  a.Activo, 
  a.Descripcion, 
  Ubi.Ubicacion, 
  saldo_sin_depreciar = a.Costo_adquisicion - d.Monto_acumulado,
  d.Periodo

FROM  
  PROVEEDORES p
    INNER JOIN ACTIVOS_FIJOS a  ON a.Proveedor = p.Proveedor
    INNER JOIN DEPRECIACIONES d ON a.Activo = d.Activo 
    INNER JOIN 
      (
        SELECT 
         MAX(d1.Monto_acumulado) AS MaxMonto 
        FROM  DEPRECIACIONES d1 
         INNER JOIN  DEPRECIACIONES d2 
           ON d1.Monto_acumulado = d2.Monto_acumulado
      ) MaxAe 
    ON d.Monto_acumulado = MaxAe.MaxMonto

    INNER JOIN ACTIVO_UBICACION Ubi ON a.activo = ubi.activo
    INNER JOIN   
      (
        SELECT 
         activo, 
         ubicacion, 
         Fecha_Ubicacion, 
         RowNum  = row_number() OVER ( partition BY activo ORDER BY abs(datediff(dd, Fecha_Ubicacion, getdate())))
        FROM  
          ACTIVO_UBICACION
      ) UbU 
    ON UbU.ubicacion = Ubi.Ubicacion 

WHERE 
    -- a.Activo IS NOT NULL AND
        UbU.RowNum = 1 

ORDER BY
  p.Proveedor

<强>评论

我已经将定义连接的WHERE条件移动到表格列表中的ON子句中,这样可以更容易地看到您如何加入表格。

请注意,所有连接都是INNER,可能不是你想要的 - 你可能需要一些LEFT JOIN,我不明白逻辑可以说。

另外,在你的游标程序中,Ubi和UbU部分似乎没有明确地与其余的表连接,所以我在activo列上写了一个INNER JOIN,因为这是表的方式加入FK关系。

在你的游标代码中,你会有效地获得一个可能错误并且运行起来也很昂贵的CROSS JOIN。

WHERE子句a.Activo IS NOT NULL不是必需的,因为INNER JOIN可以确保它。

希望这可以帮助您解决问题。

答案 1 :(得分:0)

我最终使用了另一个游标查询并修复了问题。它可能不是最佳的,但它的工作原理。每当我学习更多与数据库相关的东西时,我都会优化它。

以下是新查询:

DECLARE P CURSOR STATIC
      FOR SELECT a.Proveedor, actub.activo, actub.ubicacion FROM [SISACT].PROVEEDORES p,[SISACT].ACTIVOS_FIJOS a, (SELECT activo, ubicacion, Fecha_Ubicacion, row_number() OVER (
            partition BY activo ORDER BY abs(datediff(dd, Fecha_Ubicacion, getdate()))
          ) AS RowNum FROM [SISACT].ACTIVO_UBICACION) actub WHERE RowNum = 1 AND a.Proveedor = p.Proveedor AND actub.activo = a.Activo
      OPEN P
      FETCH NEXT FROM P INTO @p, @a, @u
                 WHILE @@FETCH_STATUS = 0
                   BEGIN 
             SELECT @activo = a.Activo, @descripcion = a.Descripcion, @costo_adquisicion = a.Costo_adquisicion, @saldo_depreciado = MaxAe.MaxMonto, @periodo = d.Periodo
                FROM [SISACT].ACTIVOS_FIJOS a, [SISACT].DEPRECIACIONES d, SISACT.PROVEEDORES pro, SISACT.ACTIVO_UBICACION actu, (SELECT MAX(d1.Monto_acumulado) AS MaxMonto FROM [SISACT].DEPRECIACIONES d1 INNER JOIN [SISACT].DEPRECIACIONES d2 ON d1.Monto_acumulado = d2.Monto_acumulado WHERE d1.Activo = @a AND d2.Activo = @a) MaxAe
                WHERE a.Activo = d.Activo AND a.Activo = @a AND d.Activo = @a AND a.Proveedor = @p AND actu.Activo = @a AND actu.Ubicacion = @u
                SET @saldo_sin_depreciar = @costo_adquisicion - @saldo_depreciado
FETCH NEXT FROM P INTO @p, @a, @u
                     END
      CLOSE P
      DEALLOCATE P