2011-02-22 33 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