2014-03-28 24 views
2

我想知道是否有一个更简单的方法来实现我的目标比我想出来的。有没有更简单的方法来编写这个查询? [MS SQL服务器]

我正在返回一个适用于对象的特定属性。对象经历多次迭代,并且属性可能会从迭代到迭代略有变化。如果属性更改,迭代只会添加到表中。所以最近的迭代可能不在表格中。

每个属性由属性ID(AttribId)和生成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将返回“其他文本”。

但是,如果没有完全匹配,我想要返回最近一代(最大的Gen ID)。例如,对象ID 32将返回“一些不同的文本”。由于没有从创3属性ID 2,它使用说明从最近的这根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比较陌生,无法想到其他任何东西。

谢谢!

回答

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。

0

尝试......

柜面逻辑没有找到该Object_table genid,配置匹配它,它映射到下一个最高genid,配置JOINON子句。

SELECT AttribDesc 
    FROM object_TABLE A 
    INNER JOIN Attribute_Table B 
     ON A.AttrbId = B.AttrbId 
      AND (
       CASE 
        WHEN A.Genid <> B.Genid 
         THEN (
           SELECT MAX(C.Genid) 
           FROM Attribute_Table C 
           WHERE A.AttrbId = C.AttrbId 
           ) 
        ELSE A.Genid 
        END 
       ) -- Selecting the right GENID in the join clause should do the job 
       = B.Genid 
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 
相关问题