需要帮助将数据集从多行转换为单行

时间:2011-12-20 20:15:36

标签: mysql sql database

我有一个数据库(MySQL),它保存了一些客户的成本记录(每个客户的项目成本不同)。任何给定的成本记录都有一个有效的日期范围(即,成本在给定的时间范围内有效)。以下是一些示例数据:

Customer    ItemNumber    EffectDate    Counter    Cost
ABC123      ITEM101       2011-12-01          0    $1.00
ABC123      ITEM101       2011-12-10          0    $1.20
ABC123      ITEM101       2011-12-10          1    $1.25
DEF456      ITEM101       2011-11-15          0    $1.10
DEF456      ITEM101       2011-12-01          0    $1.12

为了弄清楚这些数据,“计数器”变量是它被更改的次数(这是来自过时的会计平台),日期是成本的“开始日期”。因此,客户ABC123的ITEM101将在2011年12月1日和2011年12月8日的成本为1.00美元,但从12/10/2011开始,将是1.25美元(将是1.20美元,但柜台已经上涨 - 即费用现在是1.25美元)。我希望这是有道理的。

我要做的是将数据输出如下:

Customer    ItemNumber    EffectiveBegin    EffectiveEnd    Cost
ABC123      ITEM101       2011-12-01        2011-12-09      $1.00
ABC123      ITEM101       2011-12-10        2099-12-31      $1.25
DEF456      ITEM101       2011-11-15        2011-11-30      $1.10
DEF456      ITEM101       2011-12-01        2099-12-31      $1.12

12/31/2099只是“当前”的占位符日期。

任何帮助都会非常感激!!

2 个答案:

答案 0 :(得分:0)

UNTESTED :(读作:我可能至少有一个逻辑错误和2-3个语法错误)

Areas where there might be problems:

    1) B.effectiveDate-1 - Hoping B.EffectDate-1 when B.EffectDate is null 
       will retrun null so coalesce will return 12/31/2099.
    2) '12/31/2099' may need to be cast to date data type.
    3) Hoping mySQL supports date-1 to subtract 1 day.
    4) Replace "TABLE" with your table name

它的作用:

1) Joins to self in order to get begin & End for Effective dates. Excludes same
   date entries.
2) subtracts 1 from B.effectdate when customer item has multiple entries to 
   get "End"
3) Only joins records where customer, item match AND B.Counter is the MAX counter. 
   (Key if multiple entires)
4) Uses cost from B if exists, otherwise uses A.

没有进一步的麻烦:

    Select A.Customer, A.ItemNumber, A.EffectDate as EffectiveBegin, 
            coalesce(B.effectDate-1,'12/31/2099') as EffectiveEnd, 
            coalesce(B.cost, A.cost) as Cost
    FROM Table A
    LEFT JOIN Table B 
      ON A.Customer=B.Customer 
     and A.ItemNumber = B.ItemNumber 
     and A.EffectDate < B.EffectDate
     and B.Counter = (SELECT max(C.Counter) 
                      FROM Table C 
                      WHERE C.Customer = A.customer 
                        and C.ItemNumber = A.ItemNumber)

基本概述:给我最高柜台附属B记录的费用和日期-1。如果没有b记录,请使用A记录信息表示费用,使用12/31/2099表示结束日期。

答案 1 :(得分:0)

我测试了@xQbert提出的查询,但它为您的示例数据返回5行,而不是您请求的4行。

这是一个经过测试的查询,它为您的测试数据返回四行:

select p.Customer, p.ItemNumber, p.EffectDate, coalesce(e.effectdate - interval 1 day, curdate()) EffectiveEnd, p.Cost
from (
  select customer, itemnumber, effectdate, max(counter) counter
  from prices
  group by customer, itemnumber, effectdate
) c
left outer join prices p
  on p.customer = c.customer 
  and p.itemnumber = c.itemnumber 
  and p.effectdate = c.effectdate
  and p.counter = c.counter
left outer join prices e
  on e.customer = p.customer 
  and e.itemnumber = p.itemnumber 
  and e.effectdate > p.effectdate
  and e.counter = p.counter