获得最早的日期SQL复杂性

时间:2016-11-11 17:53:21

标签: sql sql-server tsql

我有一个问题,无论使用什么代码而不使用SQL SCRIPT,我都无法解决。

我有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是人员表的外键

表格中没有其他rowz

因此,我们必须显示每个人的家的详细信息

写输出的规则是

  • 如果Person在PersonH​​omes中有单一条目,则使用它
  • 如果Person在PersonH​​omes中有超过一个条目,那么我们必须查看购买日期,如果它们不同,那么使用带有OLDEST日期的PersonH​​omes ROW。并删除他的其他行
  • 如果Person在PersonH​​omes中有多个条目,那么我们必须查看购买日期,并且IF DATES是相同的,然后使用较低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 A的样本输出

ID  NAME Type HOMEID  Location    PurchaseDate

1    A    A1     5      CT          20160303

对于PERSON B

ID  NAME Type HOMEID  Location    PurchaseDate

1    A    A2     3      DT          20160101

艾登

3 个答案:

答案 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
)

答案 1 :(得分: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,但您似乎只想要一个每人一个家的结果集。

答案 2 :(得分: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