2011-02-22 32 views
1

以下查詢向我提供設備租賃公司的項目報告。這是一個超級複雜的查詢,需要將近20秒才能運行。這顯然不是獲取我正在查找的數據的正確方法。我從PHP構建這個查詢,並在02-01-2011的開始日期和03-01-2011的結束日期,產品代碼(p_code = 1)和產品池(i_pool = 1)中添加。這4條信息被傳遞給一個PHP函數,並注入到下面的sql中,以返回我需要的報表,以顯示日曆控件顯示的項目數。我的問題是:是否有任何方法可以更好地簡化或改進,或者更有效地運行,使用更好的連接或更好的方式來顯示個別日子。mysql日報表查詢

SELECT DISTINCT reportdays.reportday, count(*) 
FROM 
(SELECT '2011-02-01' + INTERVAL a + b DAY reportday 
FROM 
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 
    UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 
    UNION SELECT 8 UNION SELECT 9) d, 
(SELECT 0 b UNION SELECT 10 UNION SELECT 20 
    UNION SELECT 30 UNION SELECT 40) m 
WHERE '2011-02-01' + INTERVAL a + b DAY < '2011-03-01' 
ORDER BY a + b) as reportdays 
JOIN rental_inv as line 
    ON DATE(FROM_UNIXTIME(line.ri_delivery_dte)) <= reportdays.reportday 
    AND DATE(FROM_UNIXTIME(line.ri_pickup_dte)) >= reportdays.reportday 
LEFT OUTER JOIN rental_in as rent on line.ri_num = rent.ri_num 
LEFT OUTER JOIN rental_cancels cancelled on rent.ri_num = cancelled.ri_num 
LEFT OUTER JOIN inv inventory on line.i_num = inventory.i_num 
LEFT OUTER JOIN product ON inventory.p_code = product.p_code 
WHERE rent.ri_extend = 0  -- disregard extended rentals 
    AND cancelled.ri_num is null -- disregard cancelled rentals 
    AND inventory.p_code = 1 
    AND inventory.i_pool = 1 

GROUP BY reportdays.reportday 

如果有任何其他信息需要,讓我知道,我會發布它。

+0

我正在做一個可怕的工作來解釋這個。我需要在一個小時左右的時間內重新修改這個問題。 – stephenbayer 2011-02-22 18:51:07

+0

ri_delievery_dte和ri_pickup_dte是包含時間戳的int字段,爲什麼數據庫設計人員使用時間戳來表示我不知道的日期。我認爲日期字段會更好。如果ri_extend有一個值,那麼這意味着訂單已被替換爲新訂單,如果訂單在rental_cancels表中列出,那麼訂單已被取消,這似乎是一種模糊數據的愚蠢方式,但我沒有設計這個結構或數據庫,它已經存在了10年。 – stephenbayer 2011-02-22 20:04:20

回答

1

您可以使用:

SELECT DATE(ri_delivery) as day, 
     count(*) as itemsout, 
    FROM rental_inv 
GROUP BY day; 

我不知道,如果你需要這樣或不同的事情。

SELECT dates.day, count (*) 
    FROM rental_inv line 
     INNER JOIN (SELECT DATE(ri_delivery_dte) as day FROM rental_inv 
         WHERE ri_delivery_dte >= '2011/02/01' 
         AND ri_delivery_dte <= '2011/02/28' 
        GROUP BY day 
        UNION 
        SELECT DATE(ri_pickup_dte) as day FROM rental_inv 
         WHERE ri_pickup_dte >= '2011/02/01' 
         AND ri_pickup_dte <= '2011/02/28' 
        GROUP BY day) dates 
       ON line.ri_delivery_dte <= dates.day and line.ri_pickup_dte >= dates.day 
      LEFT JOIN rental_cancels canc on line.ri_num = canc.ri_num 
      LEFT JOIN rental_in rent on line.ri_num = rent.ri_num 
    WHERE canc.ri_num is null 
     AND rent.ri_extend = 0 
GROUP BY dates.day 
+0

稍微複雜一些,它必須是交貨日和取件日之間的項目數,並且返回格式相同,第一列爲報告日,第二列爲數量,給定二月份,2011年,應該有28行,爲2月份的每一天。 – stephenbayer 2011-02-22 18:40:45

0

,找到所有天:

SELECT DATE(IFNULL(ri_delivery,ri_pickup))AS date FROM rental_inv AS dateindex WHERE [年 - 月 - 1] = < ri_delivery < = LAST_DAY([年 - MONTH-1])OR [年 - 月 - 1] = < ri_pickup < = LAST_DAY([年 - 月 - 1])GROUP BY date具有不ISNULL(date

尋找項目出

SELECT COUNT(id)FROM rental_inv WHERE ri_pickup = [DATE]; 查找項目

SELECT COUNT(id)FROM rental_inv WHERE ri_delivery = [DATE]; 找到平衡

SELECT COUNT(out.id) - COUNT(in.id)FROM rental_inv AS出INNER JOIN rental_inv AS在 ON DATE(out.ri_pickup)= DATE(in.ri_delivery)WHERE out.ri_pickup = [DATE] OR in.ri_delivery = [DATE]

你可能會加入一切,但自其程序以來更清楚;

0

我不確定這是否是您的問題的確切答案,但我會做這樣的事情,我猜。 (我沒有使用任何SQL編輯器,所以你需要檢查我猜的語法)

SELECT 
    reportdays.d3 as d, 
    (COALESCE(outgoing.c1,0) - COALESCE(incoming.c2,0)) as c 
FROM 
-- get report dates 
(
    SELECT DATE(FROM_UNIXTIME(COALESCE(l3.ri_delivery_dte, l3.ri_pickup_dte)) d3 
    FROM rental_inv l3 
    WHERE 
     (l3.ri_delivery_dte >= UNIX_TIMESTAMP('2011-02-01') 
      AND l3.ri_delivery_dte < UNIX_TIMESTAMP('2011-03-01')) 
     OR (l3.ri_pickup_dte >= UNIX_TIMESTAMP('2011-02-01') 
      AND l3.ri_pickup_dte < UNIX_TIMESTAMP('2011-03-01')) 
    GROUP BY d3 
) as reportdays 
-- get outgoing 
LEFT JOIN ( 
    SELECT DATE(FROM_UNIXTIME(l1.ri_delivery_dte)) as d1, count(*) as c1 
    FROM rental_inv l1 
    LEFT JOIN rental_cancels canc1 on l.ri_num = canc1.ri_num 
    LEFT JOIN rental_in rent1 on l.ri_num = rent1.ri_num 
    WHERE 
     l1.ri_delivery_dte >= UNIX_TIMESTAMP('2011-02-01') 
     AND l1.ri_delivery_dte < UNIX_TIMESTAMP('2011-03-01') 
     AND canc1.ri_num is null 
     AND rent1.ri_extend = 0 
    GROUP BY d1 
) as outgoing ON reportdays.d3 = outgoing.d1 
-- get incoming 
LEFT JOIN ( 
    SELECT DATE(FROM_UNIXTIME(l2.ri_pickup_dte)) as d2, count(*) as c2 
    FROM rental_inv l2 
    LEFT JOIN rental_cancels canc2 on l2.ri_num = canc2.ri_num 
    LEFT JOIN rental_in rent2 on l2.ri_num = rent2.ri_num 
    WHERE 
     l2.ri_pickup_dte >= UNIX_TIMESTAMP('2011-02-01') 
     AND l2.ri_pickup_dte < UNIX_TIMESTAMP('2011-03-01') 
     AND canc2.ri_num is null 
     AND rent2.ri_extend = 0 
    GROUP BY d2 
) as incoming ON reportdays.d3 = incoming.d2