我需要帮助写一个复杂的SQL语句
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我需要帮助写一个复杂的SQL语句相关的知识,希望对你有一定的参考价值。
**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个表:施主表和承诺表。我想运行一个返回每对夫妇只有一个记录谁已经在往年,今年给定的,但没有(特别是最大或最近承诺日期)查询。因为最优秀的人募捐到的过去的捐献这是我们的非营利性非常重要。然而,在我们的数据库中,有时妻子给和明年丈夫给予所以它是既之下。有些没有结婚。
所以在上面的表格中,只有约翰·亚当在2012年承诺,杰克·约翰逊在2009年的承诺,应当返还。简·史密斯应该,但因为她的丈夫今年给了她自2012年给出不连返回。
我没有测试过,但像下面应该工作:
(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 <dt.spouse_id以避免重复。此外,在该查询我做了左外连接在这两种情况下,否则你可能会错过的结果。可能有轻微的语法错误,但这样的事情应该工作。我也把日期“2014年1月1日”,使其返回您在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
为了简化你可以定义一个函数,该函数。它基本上是计算配偶及捐赠者的最大价值,其中一个或多个值是空
没有确切知道你正在使用的数据库,使更难提出解决方案。我假设你的数据库支持公共表表达式和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
分贝<>小提琴here
以上是关于我需要帮助写一个复杂的SQL语句的主要内容,如果未能解决你的问题,请参考以下文章