6

我有两个表FactLik(200 万行)和UpdateStPrice(500k 行)。我需要FactLik使用规则更新表。

更新价格

| PRODUCTKEY | WAREHOUSEKEY | STARTDATE |  ENDDATE | PRIORITY | UNITPRICE |
---------------------------------------------------------------------------
|      36975 |            6 |  20120630 | 20121011 |        0 |       395 |
|      36975 |            6 |  20121018 | 20291231 |        0 |       371 |
|      36975 |            6 |  20121126 | 20121211 |      120 |       313 |
|      36975 |            6 |  20121126 | 20121219 |      120 |       288 |
|      36975 |            6 |  20121212 | 20291231 |      120 |       313 |

FactLik

|  TIMEKEY | PRODUCTKEY | PRODUCTGROUPKEY | WAREHOUSEKEY |  PRICE |
-------------------------------------------------------------------
| 20121205 |      36975 |              89 |            6 | (null) |

更新 FactLik 行的规则

  1. 同样ProductKey,在MAX 和 和之间的行中WarehouseKey找到。UpdateStPricePriorityFactLik.TimeKeyStartDateEndDate
  2. 现在找到StartDateMAX所在的行。
  3. 现在找到EndDateMIN 所在的行。

预期结果来自UpdateStPrice

| PRODUCTKEY | WAREHOUSEKEY | STARTDATE |  ENDDATE | PRIORITY | UNITPRICE |
---------------------------------------------------------------------------
|      36975 |            6 |  20121126 | 20121211 |      120 |       313 |

结果FactLik

|  TIMEKEY | PRODUCTKEY | PRODUCTGROUPKEY | WAREHOUSEKEY |  PRICE |
-------------------------------------------------------------------
| 20121205 |      36975 |              89 |            6 |    313 |

小小提琴

大提琴

我的我的查询 非常慢,实际上她的运行速度超过了 12 个小时。我在两个表上都有一些索引(建议执行计划),但它们根本没有帮助:)

因此,如果您能帮助我优化此查询,我将不胜感激。

4

3 回答 3

3

我认为你可以通过从 UpdateStPrice 订购数据来做到这一点:

UPDATE factlik
SET price =
  (SELECT TOP 1 up.unitprice
   FROM updatestprice up
   WHERE up.productkey = factlik.productkey
   AND up.warehousekey = factlik.warehousekey
   AND factlik.timekey >= up.startdate
   AND factlik.timekey <= up.enddate
   ORDER BY priority desc, startdate desc, enddate 
)

sqlfiddle在这里

于 2012-12-20T19:00:54.790 回答
0

在子查询表参考中,这似乎是为窗口函数量身定制的:

UPDATE factlik SET price = up.unitprice
FROM factlik
JOIN (SELECT factlik.timekey, factlik.productkey, factlik.warehousekey,
             up.unitprice,
             ROW_NUMBER() OVER(ORDER BY up.priority DESC, 
                                        up.startdate DESC, 
                                        up.enddate ASC) as rownum
      FROM updatestprice up
      JOIN factlik
        ON up.productkey = factlik.productkey
           AND up.warehousekey = factlik.warehousekey
           AND up.startdate <= factlik.timekey
           AND up.enddate > factlik.timekey) up
  ON up.timekey = factlik.timekey
     AND up.productkey = factlik.productkey
     AND up.warehousekey = factlik.warehousekey
     AND up.rownum = 1

运行与前面的示例相同。)

于 2012-12-20T18:50:14.470 回答
0

这应该工作:

UPDATE factlik
SET price =
    (SELECT 
        unitprice
    FROM 
        updatestprice u INNER JOIN
            (SELECT 
                ms.productkey,
                ms.warehousekey,
                max_priority,
                max_start,
                MIN(enddate) AS min_end
            FROM
                updatestprice u INNER JOIN
                factlik f ON
                    u.productkey = f.productkey AND
                    u.warehousekey = f.warehousekey AND
                    timekey >= startdate    AND 
                    timekey <= EndDate INNER JOIN
                (SELECT 
                    mp.productkey,
                    mp.warehousekey,
                    max_priority,
                    MAX(startdate) AS max_start
                FROM
                    updatestprice u INNER JOIN
                    factlik f ON
                        u.productkey = f.productkey AND
                        u.warehousekey = f.warehousekey AND
                        timekey >= startdate    AND 
                        timekey <= EndDate INNER JOIN
                        (SELECT 
                            u.productkey,
                            u.warehousekey,
                            MAX([priority]) AS max_priority
                        FROM
                            updatestprice u INNER JOIN
                            factlik f ON
                            u.productkey = f.productkey AND
                            u.warehousekey = f.warehousekey AND
                            timekey >= startdate    AND 
                            timekey <= EndDate
                        GROUP BY
                            u.productkey,
                            u.warehousekey  ) mp ON
                    u.productkey = mp.productkey AND
                    u.warehousekey = mp.warehousekey AND
                    u.priority = mp.max_priority
                GROUP BY
                    mp.productkey,
                    mp.warehousekey,
                    max_priority
                ) ms ON
                u.productkey = ms.productkey AND
                u.warehousekey = ms.warehousekey AND
                u.priority = ms.max_priority AND
                u.startdate = ms.max_start 
            GROUP BY
                ms.productkey,
                ms.warehousekey,
                max_priority, 
                max_start           
                ) me ON
        u.productkey = me.productkey AND
        u.warehousekey = me.warehousekey AND
        u.priority = me.max_priority AND
        u.startdate = me.max_start AND
        u.enddate = me.min_end)

返回:

PRODUCTKEY  WAREHOUSEKEY    STARTDATE   ENDDATE     PRIORITY    UNITPRICE
36975       0               20121018    20291231    0          371
36975       0               20120630    20121011    0          395
36975       0               20121126    20121211    100        313
36975       0               20121212    20291231    100        313
36975       0               20121126    20121219    100        288
36975       6               20120630    20121011    0          395
36975       6               20121018    20291231    0          371
36975       6               20121126    20121211    120        313
36975       6               20121126    20121219    120        288
36975       6               20121212    20291231    120        313
于 2012-12-20T19:46:41.437 回答