代码之家  ›  专栏  ›  技术社区  ›  Oscar Cabrero

在一条语句中选择两个表的联接中的第一行

  •  9
  • Oscar Cabrero  · 技术社区  · 17 年前

    我只需要从连接表a和表B的查询中选择第一行。表B上存在多个同名记录。这两个表中都没有标识符。我也不能改变方案,因为我没有DB。

    TABLE A
    NAME
    
    TABLE B
    NAME
    DATA1
    DATA2
    
    Select Distinct A.NAME,B.DATA1,B.DATA2 
    From A 
    Inner Join B on A.NAME = B.NAME
    

    这让我

    NAME       DATA1    DATA2
    sameName   1        2
    sameName   1        3
    otherName  5        7
    otherName  8        9
    

    但我只需要检索每个名字的一行

    NAME       DATA1    DATA2
    sameName   1        2
    otherName  5        7
    

    我可以通过将结果添加到带有标识列的临时表中,然后选择每个名称的最小id来实现这一点。

    这里的问题是,我需要在一个单独的声明中这样做。

    8 回复  |  直到 12 年前
        1
  •  10
  •   Rashmi Pandit    17 年前

    这将起作用:

    with temp as (
        select A.NAME, B.DATA1, B.DATA2, 
            row_number() over (partition by A.NAME order by A.NAME) as rownum
        from TABLEA A inner join TABLEB B
        on A.NAME = B.NAME
    )
    select NAME, DATA1, DATA2 from temp where rownum = 1
    

    如果要选择data1的最小值,并在其中选择data2,则使用以下变量:

    with temp as (
        select A.NAME, B.DATA1, B.DATA2, 
            row_number() over (partition by A.NAME order by B.DATA1, B.DATA2) as rownum
        from TABLEA A inner join TABLEB B
        on A.NAME = B.NAME
    )
    select NAME, DATA1, DATA2 from temp where rownum = 1
    

    这两个查询将为每个名称提供一行。

        2
  •  7
  •   Chris Thornhill    16 年前

    通过小组讨论可能会让你在一定程度上达到目的,但要小心。如果你这样做:

    Select A.NAME, min(B.DATA1), min(B.DATA2) 
    From A Inner Join B on A.NAME = B.NAME 
    Group by A.NAME;
    

    你会得到你想要的结果:

      NAME      DATA1   DATA2
      sameName   1        2    
      otherName  5        7
    

    但这只是因为你测试的数据。如果您更改了数据,那么:

    otherName  8        9
    

    你有:

    otherName  8        4
    

    它将返回:

      NAME      DATA1   DATA2
      sameName   1        2    
      otherName  5        4
    

    请注意,otherName不会从同一条记录返回DATA1和DATA2!

    更新:对其中一个数据值进行比较的自联接可能会对您有所帮助,例如:

    SELECT a.*, b.* FROM a,b 
       LEFT JOIN b b2 ON b.name = b2.name AND b.data2 < b2.data2 
       WHERE a.name = b.name AND b2.data2 IS NOT NULL;
    

    然而,只有当DATA2中的值在每个名称上都是唯一的时,这才有效。

        3
  •  0
  •   Brett Bender    17 年前

    不确定这是否能解决您的问题,但您可以尝试使用GROUP BY子句和GROUP BY其中一个名称列。

    DB2 Group by tutorial

        4
  •  0
  •   Tanktalus    17 年前

    如果你可以添加到一个临时表,然后从中查询,你可以一次完成。

    WITH T AS (temp table select), RN AS (select min row-numbers from T) SELECT T.NAME, T.DATA1, T.DATA2 FROM T INNER JOIN RN on T.row_number = RN.row_number
    

    写这篇文章还有很多其他方法,但我就是这样做的。

        5
  •  0
  •   wqw    17 年前

    试着像这样重复B

    SELECT  A.NAME, bb.DATA1, bb.DATA2 
    FROM    A 
    JOIN    B bb
    ON      A.NAME = B.NAME
    WHERE   NOT EXISTS (SELECT  *
                        FROM    B
                        WHERE   NAME = bb.NAME
                                AND (DATA1 > bb.DATA1
                                    OR DATA1 = bb.DATA1 AND DATA2 > bb.DATA2))

    如果存在更多DATAx列,请添加更多OR子句。

    如果A也包含重复项,只需在OP中使用DISTINCT。

        6
  •  0
  •   ingredient_15939    14 年前
    SELECT  A.NAME, bb.DATA1, bb.DATA2 
    From A Inner Join B on A.NAME = B.NAME
    WHERE B.DATA1 = (SELECT MIN(DATA1) FROM B WHERE NAME = A.NAME)
    

    如果B.DATA1值为 唯一的 在与表A相关的集合中。

    如果它们不是唯一的,我知道的唯一其他方法是在MSSQL 2005及更高版本中使用交叉应用。

        7
  •  0
  •   Rams    9 年前

    您可以使用row number为每个名称获取一行,请尝试以下方法

    Select name,data1,data2 from 
    (Select A.NAME,B.DATA1,B.DATA2,row_number() over(partitioj by a.name order by a.name) rn
    From A 
    Inner Join B on A.NAME = B.NAME) where rn=1
    
        8
  •  0
  •   C B dkretz    8 年前

    这个问题的标签表明它将是一个针对DB2的解决方案,但这与MS-SQL server非常相似,如果是,请尝试以下解决方案:

    使用CROSS,可以显示两个表中只存在的内容

    select A.*, B.DATA1, B.DATA2
    from A
    cross apply (select top 1 * from B where B.name = A.name) B
    

    但是,可以更改为“外部”,以显示A中存在的内容,而无需承担B中存在的义务

    select A.*, B.DATA1, B.DATA2
    from A
    OUTER apply (select top 1 * from B where B.name = A.name) B
    

    在apply语句的结构中,还可以包含ORDER语句,因为表B中没有指示出口的顺序