是否有更简单的方法来编写此查询? [MS SQL Server]

时间:2014-03-28 16:46:26

标签: sql sql-server simplify

我想知道是否有一种比我想出的更简单的方法来实现我的目标。

我正在返回一个适用于对象的特定属性。对象经历多次迭代,属性可能会从迭代到迭代略有变化。只有属性更改时,才会将迭代添加到表中。因此,最近的迭代可能不在表中。

每个属性由属性ID(AttribId)和Generation ID(GenId)的组合唯一标识。

Object_Table
ObjectId  |  AttribId  | GenId
  32      |     2      |   3
  33      |     3      |   1

Attribute_Table
AttribId | GenId | AttribDesc
  1      |   1   |   Text
  2      |   1   |   Some Text
  2      |   2   |   Some Different Text
  3      |   1   |   Other Text

当我查询特定对象时,如果可能,我希望它返回完全匹配。例如,对象ID 33将返回“其他文本”。

但如果没有完全匹配,我希望返回最新一代(最大的生成ID)。例如,对象ID 32将返回“Some Different Text”。由于Gen 3中没有属性ID 2,因此它使用属性为Gen ID 2的最新迭代中的描述。

这是我为实现这一目标而想出的:

SELECT attr.AttribDesc
FROM Attribute_Table AS attr
JOIN Object_Table AS obj
  ON obj.AttribId = obj.AttribId
WHERE attr.GenId = (SELECT MIN(GenId)
                        FROM(SELECT CASE obj2.GenId
                             WHEN attr2.GenId THEN attr2.GenId
                             ELSE(SELECT MAX(attr3.GenId)
                                   FROM Attribute_Table AS attr3
                                   JOIN Object_Table AS obj3
                                      ON obj3.AttribId = attr3.AttribId
                                   WHERE obj3.AttribId = 2
                                  )
                             END AS GenId
                             FROM Attribute_Table AS attr2
                             JOIN Object_Table AS obj2
                               ON attr2.AttribId = obj2.AttribId
                             WHERE obj2.AttribId = 2
                             ) AS ListOfGens
)

有没有更简单的方法来实现这一目标?我觉得应该有,但我对SQL比较陌生,不能想到别的什么。

谢谢!

3 个答案:

答案 0 :(得分:2)

以下查询将返回匹配值(如果找到),否则使用相关子查询返回具有最高GenId且匹配AttribId的值:

SELECT obj.Object_Id,
       CASE WHEN attr1.AttribDesc IS NOT NULL THEN attr1.AttribDesc ELSE attr2.AttribDesc END AS AttribDesc
FROM Object_Table AS obj
LEFT JOIN Attribute_Table AS attr1
  ON attr1.AttribId = obj.AttribId AND attr1.GenId = obj.GenId
LEFT JOIN Attribute_Table AS attr2
  ON attr2.AttribId = obj.AttribId AND attr2.GenId = (
        SELECT max(GenId)
        FROM Attribute_Table AS attr3
        WHERE attr3.AttribId = obj.AttribId)

如果给定的AttribId根本没有匹配的记录,它将返回NULL。如果你想在这种情况下根本没有记录,那么让第二个JOIN成为INNER JOIN而不是LEFT JOIN。

答案 1 :(得分:0)

试试这个......

如果逻辑找不到 Object_table GENID 的匹配项,则会将其映射到{ON子句中的下一个最高GENID 1}}。

JOIN

答案 2 :(得分:0)

这应该有效:

with x as (
    select *, row_number() over (partition by AttribId order by GenId desc) as rn
    from Attribute_Table
)
select isnull(a.attribdesc, x.attribdesc)
from Object_Table o
left join Attribute_Table a
on o.AttribId = a.AttribId and o.GenId = a.GenId
left join x on o.AttribId = x.AttribId and rn = 1