从同一 table sql 获取不同列的最新和最早值
Get latest and earliest value of different column from same table sql
我有一个 table,其中包含一些日期。我希望能够将 WHERE 语句应用于 return 一组,然后 return 一列中哪个日期最早,另一列中哪个日期最晚。这是一个例子 table:
ID StartDate EndDate Person Subject
1 01/03/2010 03/03/2010 Paul Math
2 12/05/2010 22/05/2010 Steve Science
3 04/03/2010 08/03/2010 Paul English
所以我想 return Person = 'Paul' 的所有记录。但是 return 类似于(最早)StartDate = 01/03/2010(来自记录 ID 1)和(最新)EndDate = 08/03/2010(来自记录 ID 3)和 Subject = English 来自最新的 EndDate(来自记录 3)。我需要两行 Paul 的上述数据和 Id.Need 所有行 person = 'Paul'
预期结果:
ID StartDate EndDate Person Subject
1 2010-03-01 2010-03-08 Paul English
3 2010-03-01 2010-03-08 Paul English
您在下面的 sql 查询中看到任何关于性能(百万条记录)的问题吗:
Select PT3.ID,PT4.EarliestStartDate AS StartDate,PT4.EndDate,PT4.Person,PT4.Subject from Data AS PT3
Join( SELECT Top 1 with ties * FROM Data AS PT
Join( SELECT PT1.Person as Person1, MIN(PT1.StartDate ) as EarliestStartDate FROM Data AS PT1 where Person ='Paul' group by PT1.Person) AS PT2 ON PT.Person =PT2.Person1WHERE Person ='Paul'
Order By Row_Number() over (Partition By PT.Person Order By PT.EndDate desc)) AS PT4 ON PT3.Person = PT4.Person
这可行:
- 首先执行
group by
以获得每个人所需的日期。
- 将分组移动到通用 table 表达式 (
cte
)。
- 返回完整数据集以获取所有行。
- 对于每个结果记录,select 对应的主题
cross apply
。
- 可选:筛选所需人员(
where
子句)。
示例数据
create table Data
(
ID int,
StartDate date,
EndDate date,
Person nvarchar(10),
Subject nvarchar(10)
);
insert into Data (ID, StartDate, EndDate, Person, Subject) values
(1, '2010-03-01', '2010-03-03', 'Paul', 'Math'),
(2, '2010-05-12', '2010-05-22', 'Steve', 'Science'),
(3, '2010-03-04', '2010-03-08', 'Paul', 'English');
解决方案
with cte as
(
select min(d.StartDate) as StartDate,
max(d.EndDate) as EndDate,
d.Person
from Data d
group by d.Person
)
select d.Id,
c.StartDate,
c.EndDate,
c.Person,
x.Subject
from cte c
join data d
on d.Person = c.Person
cross apply ( select top 1 d2.Subject
from Data d2
where d2.Person = c.Person
and d2.EndDate = c.EndDate ) x
where d.Person = 'Paul'
order by d.Person;
Fiddle 观看实际效果。
这应该会给您正确的值。
DECLARE @values TABLE (
Id INT,
StartDate DATETIME2,
EndDate DATETIME2,
Person NVARCHAR(MAX),
Subject NVARCHAR(MAX))
INSERT INTO @values VALUES
(1, '2010-03-01', '2010-03-03', 'Paul', 'Math'),
(2, '2010-05-12', '2010-05-22', 'Steve', 'Science'),
(3, '2101-03-04', '2010-03-08', 'Paul', 'English')
;WITH sort AS (
SELECT
Person,
MIN(StartDate) OVER(PARTITION BY Person) StartDate,
MAX(EndDate) OVER(PARTITION BY Person) EndDate,
Subject,
ROW_NUMBER() OVER(PARTITION BY Person ORDER BY EndDate DESC) rownum
FROM @values v)
SELECT
Person,
StartDate,
EndDate,
Subject
FROM sort
WHERE rownum = 1
它会给你以下结果:
Person MinStartDate MaxEndDate Subject
Paul 2010-03-01 2010-03-08 English
Steve 2010-05-12 2010-05-22 Science
如果您只关心 selecting 保罗的数据,这应该足够了:
SELECT
Person,
MIN(startDate) AS Earliest,
MAX(EndDate) AS Latest,
(
SELECT TOP 1 Subject
FROM Data
WHERE Person = 'Paul'
ORDER BY EndDate DESC
) AS Subject
FROM Data WHERE Person = 'Paul'
如果你想 select 所有人,这应该有效:
SELECT
d1.Person,
MIN(d1.startDate) AS Earliest,
MAX(d1.EndDate) AS Latest,
(
SELECT TOP 1 d2.Subject
FROM Data d2
WHERE d2.Person = d1.Person
ORDER BY EndDate DESC
) AS Subject
FROM Data d1
GROUP BY d1.Person
编辑:您似乎想要 table 中每一行的结果,而不是每个人一个,但总是显示最早和最晚的日期。这是你的追求吗?
SELECT
d1.Id,
d1.Person,
(
SELECT MIN(d1.StartDate) AS Earliest
FROM Data d2
WHERE d2.Person = d1.Person
) AS Earliest,
(
SELECT MAX(d1.EndDate) AS Latest
FROM Data d2
WHERE d2.Person = d1.Person
) AS Latest,
(
SELECT TOP 1 d2.Subject
FROM Data d2
WHERE d2.Person = d1.Person
ORDER BY EndDate DESC
) AS Subject
FROM Data d1
我有一个 table,其中包含一些日期。我希望能够将 WHERE 语句应用于 return 一组,然后 return 一列中哪个日期最早,另一列中哪个日期最晚。这是一个例子 table:
ID StartDate EndDate Person Subject
1 01/03/2010 03/03/2010 Paul Math
2 12/05/2010 22/05/2010 Steve Science
3 04/03/2010 08/03/2010 Paul English
所以我想 return Person = 'Paul' 的所有记录。但是 return 类似于(最早)StartDate = 01/03/2010(来自记录 ID 1)和(最新)EndDate = 08/03/2010(来自记录 ID 3)和 Subject = English 来自最新的 EndDate(来自记录 3)。我需要两行 Paul 的上述数据和 Id.Need 所有行 person = 'Paul'
预期结果:
ID StartDate EndDate Person Subject
1 2010-03-01 2010-03-08 Paul English
3 2010-03-01 2010-03-08 Paul English
您在下面的 sql 查询中看到任何关于性能(百万条记录)的问题吗:
Select PT3.ID,PT4.EarliestStartDate AS StartDate,PT4.EndDate,PT4.Person,PT4.Subject from Data AS PT3
Join( SELECT Top 1 with ties * FROM Data AS PT
Join( SELECT PT1.Person as Person1, MIN(PT1.StartDate ) as EarliestStartDate FROM Data AS PT1 where Person ='Paul' group by PT1.Person) AS PT2 ON PT.Person =PT2.Person1WHERE Person ='Paul'
Order By Row_Number() over (Partition By PT.Person Order By PT.EndDate desc)) AS PT4 ON PT3.Person = PT4.Person
这可行:
- 首先执行
group by
以获得每个人所需的日期。 - 将分组移动到通用 table 表达式 (
cte
)。 - 返回完整数据集以获取所有行。
- 对于每个结果记录,select 对应的主题
cross apply
。 - 可选:筛选所需人员(
where
子句)。
示例数据
create table Data
(
ID int,
StartDate date,
EndDate date,
Person nvarchar(10),
Subject nvarchar(10)
);
insert into Data (ID, StartDate, EndDate, Person, Subject) values
(1, '2010-03-01', '2010-03-03', 'Paul', 'Math'),
(2, '2010-05-12', '2010-05-22', 'Steve', 'Science'),
(3, '2010-03-04', '2010-03-08', 'Paul', 'English');
解决方案
with cte as
(
select min(d.StartDate) as StartDate,
max(d.EndDate) as EndDate,
d.Person
from Data d
group by d.Person
)
select d.Id,
c.StartDate,
c.EndDate,
c.Person,
x.Subject
from cte c
join data d
on d.Person = c.Person
cross apply ( select top 1 d2.Subject
from Data d2
where d2.Person = c.Person
and d2.EndDate = c.EndDate ) x
where d.Person = 'Paul'
order by d.Person;
Fiddle 观看实际效果。
这应该会给您正确的值。
DECLARE @values TABLE (
Id INT,
StartDate DATETIME2,
EndDate DATETIME2,
Person NVARCHAR(MAX),
Subject NVARCHAR(MAX))
INSERT INTO @values VALUES
(1, '2010-03-01', '2010-03-03', 'Paul', 'Math'),
(2, '2010-05-12', '2010-05-22', 'Steve', 'Science'),
(3, '2101-03-04', '2010-03-08', 'Paul', 'English')
;WITH sort AS (
SELECT
Person,
MIN(StartDate) OVER(PARTITION BY Person) StartDate,
MAX(EndDate) OVER(PARTITION BY Person) EndDate,
Subject,
ROW_NUMBER() OVER(PARTITION BY Person ORDER BY EndDate DESC) rownum
FROM @values v)
SELECT
Person,
StartDate,
EndDate,
Subject
FROM sort
WHERE rownum = 1
它会给你以下结果:
Person MinStartDate MaxEndDate Subject
Paul 2010-03-01 2010-03-08 English
Steve 2010-05-12 2010-05-22 Science
如果您只关心 selecting 保罗的数据,这应该足够了:
SELECT
Person,
MIN(startDate) AS Earliest,
MAX(EndDate) AS Latest,
(
SELECT TOP 1 Subject
FROM Data
WHERE Person = 'Paul'
ORDER BY EndDate DESC
) AS Subject
FROM Data WHERE Person = 'Paul'
如果你想 select 所有人,这应该有效:
SELECT
d1.Person,
MIN(d1.startDate) AS Earliest,
MAX(d1.EndDate) AS Latest,
(
SELECT TOP 1 d2.Subject
FROM Data d2
WHERE d2.Person = d1.Person
ORDER BY EndDate DESC
) AS Subject
FROM Data d1
GROUP BY d1.Person
编辑:您似乎想要 table 中每一行的结果,而不是每个人一个,但总是显示最早和最晚的日期。这是你的追求吗?
SELECT
d1.Id,
d1.Person,
(
SELECT MIN(d1.StartDate) AS Earliest
FROM Data d2
WHERE d2.Person = d1.Person
) AS Earliest,
(
SELECT MAX(d1.EndDate) AS Latest
FROM Data d2
WHERE d2.Person = d1.Person
) AS Latest,
(
SELECT TOP 1 d2.Subject
FROM Data d2
WHERE d2.Person = d1.Person
ORDER BY EndDate DESC
) AS Subject
FROM Data d1