**PLEDGE TABLE**
PledgeID PledgeAmount PledgeDate DonorID
---------|-------------|------------|---------
1 | 100 | 04/03/2014 | 1
2 | 200 | 04/03/2013 | 1
3 | 100 | 04/03/2009 | 2
4 | 2,000 | 01/01/2012 | 3
5 | 1,000 | 01/01/2012 | 4
6 | 500 | 01/01/2009 | 4
**DONOR TABLE**
DonorID Name SpouseID
---------|-------------|-------------
1 | John Smith | 3
2 | Jack Johnson| NULL
3 | Jane Smith | 1
4 | John Adams | NULL
我有2个表:一个捐赠者表和一个承诺表。我想运行一个查询,每个夫妇只返回一条记录(特别是最近或最近的承诺日期),这些记录在前几年但不是今年给出。这对我们的非营利组织来说非常重要,因为最好的募捐者是过去的捐赠者。然而,在我们的数据库中,有时候妻子给出了,而第二年,丈夫给予了,所以它在两者之下。有些人没有结婚。
因此,在上表中,只有John Adam在2012年的承诺和杰克约翰逊在2009年的承诺才能归还。简史密斯不应该归还,因为自2012年以来她没有给她,因为她的丈夫今年给了她。
答案 0 :(得分:0)
我还没有测试过,但以下内容应该可以使用:
(select dt.donor_id, null spouse_id, max(pledge_date) maxDate
from donor_table dt inner join pledge_table pt on (pt.donor_id = dt.donor_id)
where dt.spouse_id is null group by dt.donor_id
having max(pledge_date) is not null and max(pledge_date) < '2014-01-01'
union distinct
(select dt.donor_id, dt.spouse_id
,case when max(pt1.pledge_date) is null then max(pt2.pledge_date) else when
max(pt2.pledge_date is null then max(pt1.pledge_date) else
greatest(max(pt1.pledge_date), max(pt2.pledge_date)) end maxDate
from donor_table dt left outer join pledge_table pt1 on (pt1.donor_id = dt.donor_id)
left outer join pledge_table pt2 on (pt2.donor_id = dt.spouse_id)
where dt.donor_id < dt.spouse_id
group by dt.donor_id, dt.spouse_id
having case when max(pt1.pledge_date) is null then max(pt2.pledge_date) else when
max(pt2.pledge_date is null then max(pt1.pledge_date) else
greatest(max(pt1.pledge_date), max(pt2.pledge_date)) end is not null
and case when max(pt1.pledge_date) is null then max(pt2.pledge_date) else when
max(pt2.pledge_date is null then max(pt1.pledge_date) else
greatest(max(pt1.pledge_date), max(pt2.pledge_date)) end < '2014-01-01'
)
没有配偶的捐赠者的第一个查询返回值。第二个为我使用dt.donor_id&lt;的夫妇返回对。 dt.spouse_id以避免重复。同样在该查询中,我在两种情况下都执行左外连接,否则您可能会错过结果。可能存在轻微的语法错误,但这样的事情应该有效。我还将日期'2014-01-01'设置为返回您在2013年或之前但未在2014年捐赠的捐赠者
我正在使用mysql中最强大的功能。
看起来很复杂,因为我正在重复
case when max(pt1.pledge_date) is null then max(pt2.pledge_date) else when
max(pt2.pledge_date is null then pt1.pledge_date else
greatest(max(pt1.pledge_date), max(pt2.pledge_date)) end
为简化起见,您可以为此定义一个函数。它基本上计算配偶和捐赠者的最大价值,其中一个或多个值为空
答案 1 :(得分:0)
在不确切知道您使用哪个数据库的情况下,提出解决方案的难度要大得多。我假设您的数据库支持公用表表达式以及concat()
和year()
函数。如果这不是真的,那么有简单的选择。
这是建议的解决方案:
with couples as (
select
case when d.SpouseID IS NULL then concat('',(d.DonorID * -1))
when d.SpouseID < d.DonorID then concat(d.SpouseID,d.DonorID)
else concat(d.DonorID,d.SpouseID)
end as combinedid
, case when d.SpouseID IS NULL then d.name
when d.SpouseID < d.DonorID then concat(s.name,d.name)
else concat(d.name, s.name)
end as names
from Donors d
left join Donors s on d.spouseid = s.donorid
)
select distinct
couples.names, p.MaxPledgeYear
from couples
left join (
select
case when d.SpouseID IS NULL then concat('',(d.DonorID * -1))
when d.SpouseID < d.DonorID then concat(d.SpouseID,d.DonorID)
else concat(d.DonorID,d.SpouseID)
end as combinedid
, max(year(PledgeDate)) MaxPledgeYear
from pledges p
left join donors d on p.donorid = d.donorid
group by
case when d.SpouseID IS NULL then concat('',(d.DonorID * -1))
when d.SpouseID < d.DonorID then concat(d.SpouseID,d.DonorID)
else concat(d.DonorID,d.SpouseID)
end
) p on couples.combinedid = p.combinedid
where p.MaxPledgeYear < 2019
它产生了以下结果:
+----------------------+---------------+
| names | MaxPledgeYear |
+----------------------+---------------+
| Jack Johnson | 2009 |
| John Adams | 2012 |
| John SmithJane Smith | 2014 |
+----------------------+---------------+
从此结果中,您可以使用where子句排除“今年捐赠”的任何行。由于“今年”已经过了2014年,因此该列表中没有人承诺“今年”。
更多细节:
CREATE TABLE Pledges( PledgeID INTEGER NOT NULL PRIMARY KEY ,PledgeAmount VARCHAR(13) NOT NULL ,PledgeDate DATE NOT NULL ,DonorID INTEGER NOT NULL ); INSERT INTO Pledges(PledgeID,PledgeAmount,PledgeDate,DonorID) VALUES (1,'100','04/03/2014',1); INSERT INTO Pledges(PledgeID,PledgeAmount,PledgeDate,DonorID) VALUES (2,'200','04/03/2013',1); INSERT INTO Pledges(PledgeID,PledgeAmount,PledgeDate,DonorID) VALUES (3,'100','04/03/2009',2); INSERT INTO Pledges(PledgeID,PledgeAmount,PledgeDate,DonorID) VALUES (4,'2,000','01/01/2012',3); INSERT INTO Pledges(PledgeID,PledgeAmount,PledgeDate,DonorID) VALUES (5,'1,000','01/01/2012',4); INSERT INTO Pledges(PledgeID,PledgeAmount,PledgeDate,DonorID) VALUES (6,'500','01/01/2009',4);
CREATE TABLE Donors( DonorID INTEGER NOT NULL PRIMARY KEY ,Name VARCHAR(13) NOT NULL ,SpouseID INTEGER ); INSERT INTO Donors(DonorID,Name,SpouseID) VALUES (1,'John Smith',3); INSERT INTO Donors(DonorID,Name,SpouseID) VALUES (2,'Jack Johnson',NULL); INSERT INTO Donors(DonorID,Name,SpouseID) VALUES (3,'Jane Smith',1); INSERT INTO Donors(DonorID,Name,SpouseID) VALUES (4,'John Adams',NULL);
with couples as ( select case when d.SpouseID IS NULL then concat('',(d.DonorID * -1)) when d.SpouseID < d.DonorID then concat(d.SpouseID,d.DonorID) else concat(d.DonorID,d.SpouseID) end as combinedid , case when d.SpouseID IS NULL then d.name when d.SpouseID < d.DonorID then concat(s.name,d.name) else concat(d.name, s.name) end as names from Donors d left join Donors s on d.spouseid = s.donorid ) select * from couples
combinedid | names :--------- | :------------------- 13 | John SmithJane Smith -2 | Jack Johnson 13 | John SmithJane Smith -4 | John Adams
select case when d.SpouseID IS NULL then concat('',(d.DonorID * -1)) when d.SpouseID < d.DonorID then concat(d.SpouseID,d.DonorID) else concat(d.DonorID,d.SpouseID) end as combinedid , max(year(PledgeDate)) MaxPledgeYear from pledges p left join donors d on p.donorid = d.donorid group by case when d.SpouseID IS NULL then concat('',(d.DonorID * -1)) when d.SpouseID < d.DonorID then concat(d.SpouseID,d.DonorID) else concat(d.DonorID,d.SpouseID) end
combinedid | MaxPledgeYear :--------- | ------------: 13 | 2014 -2 | 2009 -4 | 2012
db <>提琴here