不使用临时表选择不同的记录

时间:2011-08-15 21:28:30

标签: mysql sql data-processing

我有一个第三方表,其中填充了一些杂乱的数据,我需要从中获取最新的不同记录。该表每年将被输入一个新行,或者每次“人员”更改时。该表的工作原理是最近的ActiveDate是正确的人。我已经创建了一个模拟表和数据来显示它。

CREATE TABLE `Persons` (
  `PersonId` varchar(200) NOT NULL,
  `Name` varchar(200) NOT NULL DEFAULT '',
  `ActiveDate` varchar(25) NOT NULL,
  `ExpireDate` varchar(25) DEFAULT NULL,
  `Job` varchar(200) NOT NULL DEFAULT '',
  `Position` varchar(200) NOT NULL DEFAULT ''
)

一些模拟数据:

Id       |`Name`        |ActiveDate              |ExpireDate             |Job       |`Position`
---------------------------------------------------------------------------------------------------
J1234    |Doe, John     |2010-08-15 00:00:00     |2011-08-15 00:00:00    |Worker    |Janitor
J1234    |Doe, John     |2011-08-15 00:00:00     |0000-00-00 00:00:00    |Worker    |Janitor
777      |Doe, Jane     |2010-06-04 00:00:00     |0000-00-00 00:00:00    |Boss      |Janitor
777      |Doe, Jane     |2011-04-30 00:00:00     |0000-00-00 00:00:00    |Boss      |Janitor
654G     |Smith, Jane   |2011-01-20 00:00:00     |0000-00-00 00:00:00    |Worker    |Janitor

该表还有和ExpireDate列,它实际上是由最终用户设置的,并不总是让我感到沮丧。目前我正在使用虚拟表将不同的记录拉出并存储到当天。我会使用一个临时表,但我不是100%肯定如何在MySQL中加上我不喜欢它们。我这样做的方式只是暂时希望更好的SQL。

然后必须将数据与众多其他表连接以获得最终产品。但我仍然需要处理初始的不同数据集。从一开始就加入另一张桌子就行不通了。

所以这就是我如何提取数据,存储数据,然后再将其拉出来并将其与其他表格联系起来:

INSERT INTO tmp_Person (Id, `Name`, Job, `Position`) 
    SELECT DISTINCT Id, `Name`, Job, `Position`
    FROM Person 

SELECT  tmp_Person.Id, 
    tmp_Person.`Name`, 
    tmp_Person.Job, 
    tmp_Person.`Position`,
    Pricing.Cost, 
    Pricing.Benefit

    FROM tmp_Person
    LEFT OUTER JOIN Pricing AS CL ON CL.PersonId = tmp_Person.Id 
        AND CL.PriceScredule = 'Major-Client' 
        AND CL.ExpireDate = '0000-00-00 00:00:00'
    LEFT OUTER JOIN Pricing AS Inter ON Inter.PersonId = tmp_Person.Id 
        AND Inter.PriceScredule = 'Internal-Client' 
        AND Inter.ExpireDate = '0000-00-00 00:00:00'

如何编写此代码以避免使用临时表(以任何形式)处理重复行的成本?我已经说得很清楚,如果不是我可以乐意添加或澄清。

2 个答案:

答案 0 :(得分:3)

tmp_Person替换为临时表的代码:

SELECT  tmp_Person.Id, 
    tmp_Person.`Name`, 
    tmp_Person.Job, 
    tmp_Person.`Position`,
    CL.Cost     AS MajorCost,              
    CL.Benefit  AS MajorBenefit,   
    Inter.Cost    AS InternalCost,
    Inter.Benefit AS InternalBenefit

    FROM 
      ( SELECT DISTINCT Id, `Name`, Job, `Position`
        FROM Person 
      )
      AS tmp_Person
    LEFT OUTER JOIN Pricing AS CL ON CL.PersonId = tmp_Person.Id 
        AND CL.PriceScredule = 'Major-Client' 
        AND CL.ExpireDate = '0000-00-00 00:00:00'
    LEFT OUTER JOIN Pricing AS Inter ON Inter.PersonId = tmp_Person.Id 
        AND Inter.PriceScredule = 'Internal-Client' 
        AND Inter.ExpireDate = '0000-00-00 00:00:00'

正如@Andriy发现的那样,在SELECT列表中使用Pricing.CostPricing.Benefit会引发错误。我猜你发布时忘了改变它。

答案 1 :(得分:-1)

在我意识到问题是针对mysql之前把它放在一起,但是主体应该是相同的,这将获得每个PersonID的记录以及来自Person表的最新ActiveDate。

select *
from
(
 select persons.*, ROW_NUMBER() over(partition by personid order by personid, activedate desc) as rn 
 from persons
) basedata
where basedata.rn=1