现在我正在构建一个巨大的db2查询,我从很多表中选择了大量数据(10+表上的LEFT OUTER JOIN)。大多数数据都经过精心挑选并且工作正常,但其中大部分都非常简单
但有一张桌子让我有点头疼。如果我们只是在查看sql和结果时,我们没有从这个表中选择,它看起来有点像这样:(由于数据的性质,我可以从我的SQL中给出示例)
SQL 1:
SELECT Person.Name, Date.NameOfDate, Location.City
FROM Person LEFT OUTER JOIN
Date ON Person.Id = Date.PersonId LEFT OUTER JOIN
Location ON Date.LocationId = Location.Id
WHERE Person.IsAlive = True
结果1:
Name - NameOfDate - City
Peter - Anna - Athen
Peter - Caroline - Washington
Simone - Carl - Athen
现在我有一张桌子(让他们称之为'评论')。此表有一些关于城市的额外信息。每个城市可以有几行。例如:
SQL 2:
SELECT Location.City, Comment.Text, Comment.SortingId, Comment.TypeOfData
FROM Location LEFT OUTER JOIN
Comment ON Location.Id = Comment.LocationId
结果2:
City - Text - SortingId - TypeOfData
New York - Do not read this - 1 - 777
Washington - This text is irrelevant - 1 - 555
Washington - Make sure you visit the White House - 2 - 777
Washington - On saturdays there is a market near the docks - 3 - 777
Athen - Bring translator - 1
我的问题是我需要在SQL 1中检索Comment.Text,但只检索SortingId最低的行,其中TypeOfData是777.结果应该是这样的:
Name - NameOfDate - City - Text
Peter - Anna - Athen - Bring translator
Peter - Caroline - Washington - Make sure you visit the White House
Simone - Carl - Athen - Bring translator
我设法获得此数据的最接近的事情如下:
SELECT Person.Name, Date.NameOfDate, Location.City, Comment.Text
FROM Person LEFT OUTER JOIN
Date ON Person.Id = Date.PersonId LEFT OUTER JOIN
Location ON Date.LocationId = Location.Id LEFT OUTER JOIN
(SELECT Comment.Text FROM Comment ORDER BY Comment.SortingId FETCH FIRST 1 ROWS ONLY) AS Comment ON Location.Id = Comment.LocationId
WHERE Person.IsAlive = True
但有些人可能已经注意到了,这并没有给我任何结果。子选择将返回纽约行,然后它将在LocationId上过滤,它将删除纽约,不留任何东西
还有其他想法吗?
编辑:
评论表没有任何唯一的ID字段。你可以有两行,唯一的区别是SortingId,但是同一个SortingId可以在很多行中使用,例如SortingId可以是两行中的1,具有不同的LocationId
答案 0 :(得分:0)
您可以尝试使用注释在子查询中加入位置表,类似这样的
(SELECT Comment.Text FROM Locat LEFT OUTER JOIN
Comment ON Locat.Id = Comment.LocationId
WHERE Locat.City = Location.City
ORDER BY Comment.SortingId
FETCH FIRST 1 ROWS ONLY)
答案 1 :(得分:0)
您的SELECT子查询生成一个表,其中包含一行,其中SortingId 整体最低。您可能想要的是具有最低SortingId 的1行,用于手头的城市。
将WHERE子句添加到应用此条件的SELECT子查询中。可能是这种情况(事实上,我认为很可能是这种情况)因为您的Location.Id超出了范围而无法写入这种情况"在WHERE子句中。
如果是这样,请从子查询中删除ORDER和FETCH子句,并在" outermost"中恢复所需的过滤。在哪里以
的形式AND NOT EXISTS (
SELECT *
FROM Comment AS SECONDCOMMENT
WHERE cities-the-same AND SECONDCOMMENT.SortingId > Comment.SortingId
)
答案 2 :(得分:0)
您可以使用DENSE_RANK()
分析函数。您的样本数据似乎有点不一致(雅典没有Comment.TypeOfData
值)但是请尝试以下几点:
SELECT * FROM (
SELECT
l.city, c.text, c.sortingid, c.typeofdata ,
DENSE_RANK() OVER (PARTITION BY c.locationid ORDER BY c.sortingid) rnk
FROM location l
LEFT JOIN comment c
ON l.id = c.locationid
AND c.typeofdata = 777
) t
WHERE rnk = 1
PS。您的问题明确要求进行子选择,并且在此解决方案中, 是一个子选择,尽管可能不是您认为可能的位置。
答案 3 :(得分:0)
从9.7开始的DB2有一种方法可以使用窗口函数。
具体为FIRST_VALUE。它的工作原理如下:
SELECT Location.ID, Location.City, C.Text, C.SortingID, C.TypeOfData
FROM Location
LEFT OUTER JOIN (
SELECT DISTINCT LocationID
FIRST_VALUE(Text) OVER (PARTITION BY LocationID ORDER BY SortingId) as Text,
FIRST_VALUE(SortingId) OVER (PARTITION BY LocationID ORDER BY SortingId) as SortingID,
FIRST_VALUE(TypeOfData) OVER (PARTITION BY LocationID ORDER BY SortingId) as Typeofdata
FROM Comment
) AS C ON Location.Id = C.LocationId
每个城市每个ID将返回1行
答案 4 :(得分:0)
试试这个
SELECT Person.Name, Date.NameOfDate, Location.City, tmp.Text
FROM Person
LEFT OUTER JOIN Date ON Person.Id = Date.PersonId
LEFT OUTER JOIN Location ON Date.LocationId = Location.Id
LEFT OUTER JOIN LATERAL(
select Text FROM Comment
where Location.Id = Comment.LocationId and Comment.TypeOfData=777
order by Comment.SortingId
fetch first rows only
) tmp on 1=1
WHERE Person.IsAlive = True