2009-04-21 33 views
9

我只需要选择连接表A和B的查询中的第一行。在表B上存在多个具有相同名称的记录。这两个表格中没有任何标识符。我无法改变计划,因为我没有拥有数据库。在一个语句中选择两个表的连接中的第一行

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 

我能够通过添加结果到一个临时表与要做到这一点标识列,然后选择每个名称的最小标识。

这里的问题是,我需要在一个单一的陈述中这样做。

回答

0

不知道这是否能解决您的问题,但您可以尝试使用GROUP BY子句并按名称列之一进行分组。

DB2 Group by tutorial

7

使用GROUP BY可能让你中途有,但要小心。如果你做这样的事情:

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 

需要注意的是中文别名不从返回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值是每个名称唯一工作。

+0

上一条语句有小错字。它应该是“IS NOT NULL”而不是“IN NOT NULL”。 – mbp 2010-03-17 20:27:32

+0

+1你是一个救世主。由于SQL CE的限制,即使使用SQL CE,您编辑的自连接也可以工作,因为此问题的其他解决方案并不适用。 – 2012-04-27 06:43:48

0

如果您可以添加到临时表然后从中进行查询,则可以一次完成。

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 

有很多其他的方式来写这个,但这就是我一直在做类似的事情。

0

尝试重复数据删除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))

添加更多或条款是否存在更多的数据X列。

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

10

这将工作:

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 

如果你想选择数据1的最低值,并将其数据2中,然后利用这种变化:

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 

这两个查询会给每一个行名称。

0
​​

这会给你想要的结果,提供B.DATA1值是与表A

如果他们不是唯一的集内独特,我唯一知道的另一种方式是使用在MSSQL 2005及以上版本中交叉应用。

0

这个问题的标签表明,这将是DB2的解决方案,但是这是非常相似的MS-SQL服务器,如果是这样尝试以下解决方案:

使用交叉,将有可能显示什么只存在于两个表

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

但它有可能改变到OUTER显示在一个什么不存在的义务在乙

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

存在在structu因为在表B中没有关于退出顺序的指示,所以也可能包含ORDER语句。

0

您可以使用行号为每个名称获取一行,尝试类似低于

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 
相关问题