我只需要从连接表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
我能够通过将结果添加到带有标识列的临时表中,然后选择每个名称的最小标识来实现此目的。
这里的问题是我需要在一个声明中执行此操作。
答案 0 :(得分: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
如果要选择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
两个查询都会为每个名称提供一行。
答案 1 :(得分: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
请注意,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中的值对每个NAME唯一时才会有效。
答案 2 :(得分:0)
不确定这是否能解决您的问题,但您可以尝试使用GROUP BY子句并按名称列之一进行分组。
答案 3 :(得分: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
还有很多其他方法可以写这个,但这就是我一直在做类似的事情。
答案 4 :(得分: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))
如果存在更多DATAx列,则添加更多OR子句。
如果A也包含重复项,只需使用OP中的DISTINCT。
答案 5 :(得分:0)
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)
这将提供您想要的结果,只要在与表A相关的集合中提供B.DATA1值唯一。
如果它们不是唯一的,我知道的另一种方法是在MSSQL 2005及更高版本中使用CROSS APPLY。
答案 6 :(得分:0)
此问题的标记表明它将是DB2的解决方案,但这与MS-SQL服务器非常相似,如果是这样,请尝试以下解决方案:
使用CROSS,可以显示仅存在于两个表中的内容
select A.*, B.DATA1, B.DATA2
from A
cross apply (select top 1 * from B where B.name = A.name) B
但是可以更改为OUTER以显示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中没有表示退出的顺序
答案 7 :(得分: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