6

I have Two tables FactLik (2 million rows) and UpdateStPrice ( 500k rows). I need to update FactLik table using rules.

UpdateStPrice

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

Rules for updating FactLik row

  1. For same ProductKey, WarehouseKey find in UpdateStPrice row where Priority is MAX and FactLik.TimeKey is between StartDate and EndDate.
  2. Now find row where StartDate is MAX.
  3. Now find row where EndDate is MIN.

ExpectedResult from UpdateStPrice:

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

Result FactLik:

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

SmallFiddle

BigFiddle

I have My QUERY which is very slow, actually she running to slow more than 12 hours. I have some Indexes on both tables (Execution plan suggested) but they don' help at all:)

So If you can help me to optimize this query I'll be very grateful.

4

3 に答える 3

3

I think you can do this by just ordering the data from 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 here

于 2012-12-20T19:00:54.790 に答える
0

This seems tailor-made for a windowing function, in a subquery table-reference:

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

(Runs the same as the earlier example.)

于 2012-12-20T18:50:14.470 に答える
0

this should work:

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)

returns:

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 に答える