代码之家  ›  专栏  ›  技术社区  ›  Mason Wheeler

如何修改此查询而不增加返回的行数?

  •  1
  • Mason Wheeler  · 技术社区  · 14 年前

    left outer join
      (select distinct ID from OTHER_TABLE) as MYJOIN
    on BASE_OBJECT.ID = MYJOIN.ID
    

    这很简单。检查要查询的主对象和其他表所表示的对象之间是否存在某种关系 MYJOIN.ID 在有问题的行上为空。

    但现在要求有了一些变化。房间里还有一排 OTHER_TABLE 值可以为1或0,查询需要知道1值的主对象之间是否存在关系,以及0值是否存在关系。显而易见的解决办法是:

    left outer join
      (select distinct ID, TYPE_VALUE from OTHER_TABLE) as MYJOIN
    on BASE_OBJECT.ID = MYJOIN.ID
    

    但这样做是错误的,因为如果0-type和1-type对象都存在于同一个ID中,则会增加查询返回的行数,这是不可接受的。所以我需要的是某种subselect,它将为每个不同的ID返回1行,其中包含一个“1-type exists”列和一个“0-type exists”列。我不知道如何用SQL编写代码。

    例如,对于下表,

    ID   | TYPE_VALUE
    _________________
    1    | 1
    3    | 0
    3    | 1
    4    | 0
    

    我希望看到这样的结果集:

    ID   | HAS_TYPE_0 | HAS_TYPE_1
    ______________________________
    1    | 0          | 1
    3    | 1          | 1
    4    | 1          | 0
    

    2 回复  |  直到 14 年前
        1
  •  3
  •   Dave Markle    14 年前

    SELECT DISTINCT ID,
        CASE WHEN EXISTS (
                SELECT * FROM Table1 y 
                WHERE y.TYPE_VALUE = 0 AND ID = x.ID) 
            THEN 1 
            ELSE 0 END AS HAS_TYPE_0,
        CASE WHEN EXISTS (
                SELECT * FROM Table1 y
                WHERE y.TYPE_VALUE = 1 AND ID = x.ID) 
            THEN 1 
            ELSE 0 END AS HAS_TYPE_1
    FROM Table1 x;
    

    如果表中有大量的元素,那么它的性能就不会那么好了——这些嵌套的子选择在性能方面往往是致命一击。

    SELECT 
         ID,
         CASE WHEN MIN(TYPE_VALUE) = 0 THEN '1' ELSE 0 END AS HAS_TYPE_0,
         CASE WHEN MAX(TYPE_VALUE) = 1 THEN '1' ELSE 0 END AS HAS_TYPE_1
    FROM Table1
    GROUP BY ID;
    
        2
  •  2
  •   a1ex07    14 年前

    select distinct ID, TYPE_VALUE from OTHER_TABLE 使用

    select ID,  
    MAX(CASE WHEN TYPE_VALUE =0 THEN 1 END) as has_type_0,  
    MAX(CASE WHEN TYPE_VALUE =1 THEN 1 END) as has_type_1  
    from OTHER_TABLE
    GROUP BY ID;
    

    你也可以使用 PIVOT