SQL:查找字段值不同的行

时间:2009-06-05 16:42:07

标签: sql sql-server

我有一个像这样结构化的数据库表(为简洁起见省略了相关字段):

rankings
------------------
(PK) indicator_id
(PK) alternative_id
(PK) analysis_id
rank

所有字段都是整数;前三个(标记为“(PK)”)是复合主键。给定的“分析”有多个“替代”,每个“替代”对于许多“指标”中的每一个都具有“等级”。

我正在寻找一种有效的方法来比较任意数量的分析,其中任何替代/指标组合的等级不同。因此,例如,如果我们有这些数据:

analysis_id | alternative_id | indicator_id | rank
----------------------------------------------------
          1 |              1 |            1 |    4
          1 |              1 |            2 |    6
          1 |              2 |            1 |    3
          1 |              2 |            2 |    9
          2 |              1 |            1 |    4
          2 |              1 |            2 |    7
          2 |              2 |            1 |    4
          2 |              2 |            2 |    9

...然后理想的方法将确定以下差异:

analysis_id | alternative_id | indicator_id | rank
----------------------------------------------------
          1 |              1 |            2 |    6
          2 |              1 |            2 |    7
          1 |              2 |            1 |    3
          2 |              2 |            1 |    4

我提出了一个查询,它可以为2个分析ID执行我想要的操作,但是我无法概括它以查找任意数量的分析ID之间的差异(即用户可能想要比较2或5,或者9,或者其他什么,找到任何至少有一个分析与其他分析不同的行)。我的疑问是:

declare @analysisId1 int, @analysisId2 int;
select @analysisId1 = 1, @analysisId2 = 2;

select 
    r1.indicator_id, 
    r1.alternative_id,
    r1.[rank] as Analysis1Rank,
    r2.[rank] as Analysis2Rank
from rankings r1
inner join rankings r2
    on r1.indicator_id = r2.indicator_id
        and r1.alternative_id = r2.alternative_id
        and r2.analysis_id = @analysisId2
where
    r1.analysis_id = @analysisId1
    and r1.[rank] != r2.[rank]

(它将分析值放入其他字段而不是行。我认为无论哪种方式都可行。)

如何概括此查询以处理许多分析ID? (或者,或者,提出一个不同的,更好的查询来完成这项工作?)我正在使用SQL Server 2005,以防万一。

如果有必要,我总是可以从表中提取所有数据并查找代码中的差异,但是SQL解决方案会更好,因为我通常只关心几千行中的几行而且没有任何意义。如果我可以避免它,将它们全部转移。 (但是,如果你有令人信服的理由不在SQL中这样做,那么这样说 - 我也认为这也是一个很好的答案!)

4 个答案:

答案 0 :(得分:2)

这将返回您想要的数据集 - 现在您只需要一种方法将所需的分析ID传递给查询。或者只是在您的应用程序中过滤此数据。

    select r.* from rankings r
    inner join
    (
        select alternative_id, indicator_id
        from rankings
        group by alternative_id, indicator_id
        having count(distinct rank) > 1
    ) differ on r.alternative_id = differ.alternative_id
    and r.indicator_id = differ.indicator_id
    order by r.alternative_id, r.indicator_id, r.analysis_id, r.rank

答案 1 :(得分:1)

我不知道您使用的是哪个数据库,在SQL Server中我会这样:

-- STEP 1, create temporary table with all the alternative_id , indicator_id combinations with more than one rank:
select alternative_id , indicator_id
into #results
from rankings 
group by alternative_id , indicator_id
having count (distinct rank)>1

-- STEP 2, retreive the data

select a.* from rankings a, #results b
where a.alternative_id  = b.alternative_id
and  a.indicator_id = b. indicator_id
order by alternative_id , indicator_id, analysis_id 
顺便说一下,这里给出的其他答案需要计数(不同级别)!!!!!

答案 2 :(得分:0)

我认为这就是你要做的事情:

select 
    r.analysis_id, 
    r.alternative_id, 
    rm.indicator_id_max,
    rm.rank_max
from rankings rm
    join (
        select 
            analysis_id, 
            alternative_id, 
            max(indicator_id) as indicator_id_max, 
            max(rank) as rank_max 
        from rankings 
        group by analysis_id, 
            alternative_id 
        having count(*) > 1
    ) as rm
    on r.analysis_id = rm.analysis_id
    and r.alternative_id = rm.alternative_id

答案 3 :(得分:0)

你的例子差异似乎是错误的。您说您想要分析,其中任何备选/指标组合的等级不同但示例行3和4不满足此条件。根据您的要求得出的正确结果是:

 analysis_id | alternative_id | indicator_id | rank
 ----------------------------------------------------
      1 |              1 |            2 |    6
      2 |              1 |            2 |    7
      1 |              2 |            1 |    3
      2 |              2 |            1 |    4

您可以尝试查询:

with distinct_ranks as (
    select alternative_id  
    , indicator_id
    , rank
    , count (*) as count
    from rankings
        group by alternative_id  
        , indicator_id
        , rank
    having count(*) = 1)
select r.analysis_id
    , r.alternative_id  
    , r.indicator_id
    , r.rank
from rankings r
    join distinct_ranks d on r.alternative_id = d.alternative_id
        and r.indicator_id = d.indicator_id
        and r.rank = d.rank

你必须意识到,在多重分析中,你所拥有的标准是模棱两可的。如果分析1,2和3的等级1和4,5和6的替代/指标1/1的等级2怎么办?集合(1,2,3)与集合(4,5,6)“不同”,但在每个集合内部没有区别。在这种情况下你想要的行为是什么,如果他们出现了?我的查询查找所有其他分析中相同备选/指标*具有不同排名的所有记录',但不清楚这是否符合您的要求。