2016-11-11 107 views
2

我遇到了一个问题,即使不使用代码而不是使用SQL SCRIPT,也无法解决问题。获取最大日期SQL复杂性

我有2个表

Person 
ID  Name  Type 
    1  A   A1 
    2  B   A2 
    3  C   A3 
    4  D   A4 
    5  E   A6 


PersonHomes 

HOMEID   Location  PurchaseDate PersonID 
    1   CA   20160101   1 
    2   CT   20160202   1 
    3   DT   20160101   2 
    4   BT   20170102   3 
    5   CT   20160303   1 
    6   CA   20160101   2 

是PersonID是Person表的外键

有表

所以在没有其他rowz,我们已经表现出每个人提供家庭详细

写输出的规则是

  • IF人在PersonH​​omes单一入口,然后用它
  • 如果伤者已超过在PersonH​​omes一个条目接下来我们就来看看购买之日起,如果不同,那么在它最早日期使用PersonH​​omes ROW。并删除了他的其他行
  • IF人在PersonH​​omes不止一个条目,然后我们来看看在购买日期和IF日期都相同,则使用行以较低的ID,然后删除HIM的
其他行

这是很容易在代码中做,但使用SQL它是复杂

我试过是

WITH PERSON (
SELECT * FROM Person) 

SELECT * FROM PERSON 
INNER JOIN PersonHomes ON Person.ID = PersonHomes.PersonID 
WHERE PersonHomes.PersonID = CASE WHEN (COUNT (*) FROM PersonHomes...) 

那么我想我可以写SQL函数?

我卡住了,请帮忙!

对person的

ID NAME Type HOMEID Location PurchaseDate 

1 A A1  5  CT   20160303 

示例输出某乙

ID NAME Type HOMEID Location PurchaseDate 

1 A A2  3  DT   20160101 

艾登

+0

我删除了MySQL的标签,因为语法显然不是MySQL的。 –

回答

1

你似乎有一个优先查询。我会解决这个使用row_number()

select ph.* 
from (select ph.*, 
      row_number() over (partition by personid 
           order by purchasedate asc, homeid asc 
           ) as seqnum 
     from personhomes ph 
    ) ph 
where seqnum = 1; 

这实际上并没有改变表中的数据。虽然你说delete,但你似乎只想要一个结果集与每个人一个家。

+0

您可以在下面查看我的答案吗?我认为我们可以通过这种方式解决它? – Aiden

+1

你的逻辑很复杂:(对不起,我不是专家,其他行在你的SQL中被删除了吗?你能简单地解释一下你的逻辑吗?实际上我也必须删除这些行:( – Aiden

0

这是Link

;WITH cte AS 
(
    SELECT *, RowN = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY AddressMoveDate DESC) FROM Address 
) 
DELETE FROM cte WHERE RowN > 1 
+0

它可能很短,但似乎删除错误的行 –

2

了最短的做法也不是那么容易得到所需的输出与SQL。我们应该写多个SQL查询。

首先,我创建了包括家居细节的临时表:

select PersonID, count(*) as HomeCount, count(distinct PurchaseDate) as 
PurchaseDateCount, min(PurchaseDate) oldestPurchaseDate, min(HOMEID) as 
LowerHomeID into #PersonHomesAbstractTable from PersonHomes group by PersonID 

然后你的第一个规则的输出:

select p.ID, p.NAME, p.Type, ph.HOMEID, ph.Location, ph.PurchaseDate from Person p 
inner join #PersonHomesAbstractTable a on p.ID = a.PersonID 
inner join PersonHomes ph on p.ID = ph.PersonID 
where a.HomeCount = 1 

对于你的第二个规则的输出:

select p.ID, p.NAME, p.Type, ph.HOMEID, ph.Location, ph.PurchaseDate 
from Person p inner join #PersonHomesAbstractTable a on p.ID = a.PersonID 
inner join PersonHomes ph on p.ID = ph.PersonID and 
ph.PurchaseDate = a.oldestPurchaseDate 
where a.HomeCount > 1 and a.PurchaseDateCount <> 1 

最后为您的第三条规则的输出:

select p.ID, p.NAME, p.Type, ph.HOMEID, ph.Location, ph.PurchaseDate 
from Person p inner join #PersonHomesAbstractTable a on p.ID = a.PersonID 
inner join PersonHomes ph on p.ID = ph.PersonID and 
ph.HOMEID = a.LowerHomeID 
where a.HomeCount > 1 and a.PurchaseDateCount = 1 

当然还有其他一些方法,但现在这种方式出现在我的脑海里。

如果你想删除不需要的行,你可以使用下面的脚本:

delete from PersonHomes where HOMEID in 
(
    select ph.HOMEID from #PersonHomesAbstractTable a 
    inner join PersonHomes ph on a.PersonID = ph.PersonID and 
    ph.PurchaseDate <> a.oldestPurchaseDate 
    where a.HomeCount > 1 and a.PurchaseDateCount <> 1 

    union 

    select p.HOMEID from #PersonHomesAbstractTable a 
    inner join PersonHomes ph on a.PersonID = ph.PersonID and 
    ph.HOMEID <> a.LowerHomeID 
    where a.HomeCount > 1 and a.PurchaseDateCount = 1 
) 
+0

谢谢,这是正确的答案,我们只是通过使用临时表来记录我们在每一步中所做的事情 – Aiden