JOIN tables, only selecting newest row from second table, and conditional on second table data

huangapple go评论58阅读模式
英文:

JOIN tables, only selecting newest row from second table, and conditional on second table data

问题

对于第一个部分的问题,是的,你可以使用LEFT JOIN来获取每个人在Hair Colors表中的最新行。结果应该如下:

| People_index | Name   | Color | Color-change time |
| ----- | ------ | ----- | ----- |
| 1     | Bob    | Green | 5:45  |
| 2     | Susie  | Black | 5:02  |

对于第二个部分的问题,你可以使用类似的SQL查询,但是在选择最新行的基础上,也只选择等于特定值的行。例如,只选择最新的头发颜色为绿色的人:

| People_index | Name   | Color | Color-change time |
| ----- | ------ | ----- | ----- |
| 1     | Bob    | Green | 5:45  |
英文:

Say I have two tables. One has the main details, such as each row is a person and has their name. The second row contains every revision when someone changes "Hair color".

People

People_index Name
1 Bob
2 Susie

Hair colors

Hair_index People_index Color Color-change time
1 1 Brown 5:03
2 1 Red 5:07
3 1 Green 5:45
4 2 Black 5:02

Is there a way to LEFT JOIN the two tables so that for each row in People, I only get the newest row for each person in Hair Colors?

So, the result should be:

People_index Name Color Color-change time
1 Bob Green 5:45
2 Susie Black 5:02

And then, for the other part of my app, I'd like similar SQL, but on top of selecting the newest row, it also only selects the rows that equal a certain value. For example, only select people where the most recent hair color is Green:

People_index Name Color Color-change time
1 Bob Green 5:45

Right now, I just select all people first, then looping through the rows, I check whether the newest hair color row is Green for each person and decide whether to add the person to the final array that way, but it seems that it could be a lot more efficient.

答案1

得分: 1

尝试这个:

with PeopleAllHC as (
	select 
		  P.People_index	
		, P.Name
		, HC.Color
		, HC.Color_change_time
		, Seq=row_number() over (partition by P.People_Index order by HC.Color_change_time desc)
	from 
		People P
		inner join
		HairColors HC
		on P.People_Index=HC.People_Index
)
select 
	  People_index	
	, Name
	, Color
	, Color_change_time
from PeopleAllHC
where Seq=1
and Color='绿色'

我们在公共表达式(CTE)中获取所有的发色变化,使用row_number() over函数对它们按照变化时间从最近到最旧进行编号(这将分配1给最近的变化),将其称为PeopleAllHC。然后,我们选择Seq=1的行以限制输出为我们想要的颜色的最新变化。

(我已更改了您的表/列名称以避免使用分隔符 - 反引号/括号/双引号 - 这些取决于数据库管理系统;您可能需要相应调整它们。)

英文:

Try this:

with PeopleAllHC as (
	select 
		  P.People_index	
		, P.Name
		, HC.Color
		, HC.Color_change_time
		, Seq=row_number() over (partition by P.People_Index order by HC.Color_change_time desc)
	from 
		People P
		inner join
		HairColors HC
		on P.People_Index=HC.People_Index
)
select 
	  People_index	
	, Name
	, Color
	, Color_change_time
from PeopleAllHC
where Seq=1
and Color='Green'

We get all hair colour changes in the CTE, number the changes from most-recent to oldest using the row_number() over function (this will assign 1 to the most recent) calling it PeopleAllHC. We then select the rows with Seq=1 to limit the output to the latest with the color we want.

(I have changed your table/column names to avoid using delimiters -backticks/brackets/double quotes- ; these are dbms dependent; you may need to adjust them accordingly)

huangapple
  • 本文由 发表于 2023年5月11日 07:30:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76223206.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定