Select the first row in a join of two tables in one statement

后端 未结 8 1776
名媛妹妹
名媛妹妹 2020-12-29 12:59

I need to select only the first row from a query that joins tables A and B. On table B exist multiple records with same name. There are not identifiers in any of the two tab

相关标签:
8条回答
  • 2020-12-29 13:24

    This will work:

    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
    

    If you want to select the least value of data1 and within it data2, then use this variation:

    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
    

    Both the queries will give one row per name.

    0 讨论(0)
  • 2020-12-29 13:26
    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)
    

    This will give your desired result, providing B.DATA1 values are unique within the set relating to table A.

    If they're not unique, the only other way I know is using CROSS APPLY in MSSQL 2005 and above.

    0 讨论(0)
  • 2020-12-29 13:26

    You can use row number to get one row for each name, try something like below

    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
    
    0 讨论(0)
  • 2020-12-29 13:29

    Try to dedupe B like this

    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))

    Add more OR clauses if more DATAx columns exist.

    If A contains duplicates too, simply use DISTINCT as in the OP.

    0 讨论(0)
  • 2020-12-29 13:35

    Using a GROUP BY may get you part way there, but beware. If you do something like this:

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

    You will get the result you are looking for:

      NAME      DATA1   DATA2
      sameName   1        2    
      otherName  5        7
    

    But only because of the data you are testing with. If you change the data, so that instead of:

    otherName  8        9
    

    you had:

    otherName  8        4
    

    It would return:

      NAME      DATA1   DATA2
      sameName   1        2    
      otherName  5        4
    

    Note that otherName does not return DATA1 and DATA2 from the same record!

    Update: A self-join with a comparison on one of the data values may help you, such as:

    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;
    

    However, this will only work if the values in DATA2 are unique per NAME.

    0 讨论(0)
  • 2020-12-29 13:45

    Not sure if this will solve your problem or not, but you could try using the GROUP BY clause and group by one of the name columns.

    DB2 Group by tutorial

    0 讨论(0)
提交回复
热议问题