2012-03-22 130 views
1

我需要一个帮助头脑风暴的查询。我有一个销售表,每个餐厅位置有两行(每天)。一行是AM销售,另一行是PM销售。 AM销售实际上只是AM销售,然而,PM销售是AM销售和PM销售的组合。因此,为了提取PM销售额,您必须从其中减去AM销售额。MySQL查询 - 两行之间的差异

--------------------------------------------------------- 
    date | id | meridiem | daily_sales | cover_counts | 
--------------------------------------------------------- 
2012-03-22 |103 | AM  | 2956.32 | 175  | 
2012-03-22 |103 | PM  | 12124.62 | 484  | 
--------------------------------------------------------- 

我有一个查询来计算预计午餐每人平均(这是从AM销售),它很好。它基本上从前6周的销售数据中提取前四周,并对其进行平均。 (注:按人均销售额除以销售额计算)。

$statement = "SELECT directory.location, ROUND((SUM(sales.daily_sales/sales.cover_counts)/4), 2) AS lppa 
       FROM t_directory directory 
       LEFT JOIN t_sales sales 
       ON sales.site_id = directory.site_id 
       AND DAYOFWEEK(sales.business_date) = DAYOFWEEK(:date1) 
       AND sales.business_date < DATE_SUB(:date2, INTERVAL 14 DAY) 
       AND sales.business_date >= DATE_SUB(:date3, INTERVAL 42 DAY)     
       AND sales.meridiem = 'AM' 
       WHERE directory.active = 1 
       GROUP BY directory.site_id 
       ORDER BY directory.site_id ASC 
       LIMIT :totalLocations"; 

$statementHandle = $this->dbHandle->prepare($statement); 
$statementHandle->bindValue(':date1', $this->date, PDO::PARAM_STR); 
$statementHandle->bindValue(':date2', $this->date, PDO::PARAM_STR); 
$statementHandle->bindValue(':date3', $this->date, PDO::PARAM_STR); 
$statementHandle->bindValue(':totalLocations', $this->totalLocations, PDO::PARAM_INT); 
$statementHandle->execute(); 
$lppa = $statementHandle->fetchAll(PDO::FETCH_ASSOC); 

现在我想计算每人的平均晚餐。为了做到这一点,我将不得不减去AM销售额,并分别在PM算出任何数学之前从PM销售额和盖子中扣除。有没有一种简单的方法来实现这一切到一个查询?我明显可以用PHP来做到这一点,但我只是很好奇这是如何在查询中完成的。任何帮助或见解将不胜感激。请让我知道是否需要更多细节。

回答

2

可以做重新加入到t_sales中,然后过滤 'PM'

SELECT DIRECTORY.location, 
     Round((SUM(salesPM.daily_sales - salesAM.daily_sales/
        salesPM.cover_counts - salesAM.cover_counts)/4), 2) 
         AS lppaPM 
FROM t_directory DIRECTORY 
     LEFT JOIN t_sales salesAM 
     ON salesAM.site_id = DIRECTORY.site_id 
      AND Dayofweek(salesAM.business_date) = Dayofweek(:date1) 
      AND salesAM.business_date < DATE_SUB(:date2, INTERVAL 14 DAY) 
      AND salesAM.business_date >= DATE_SUB(:date3, INTERVAL 42 DAY) 
      AND salesAM.meridiem = 'AM' 
     LEFT JOIN t_sales salespm 
     ON salesAM.site_id = salesPM.site_id 
      AND salesAM.business_date = salesPM.business_date 
      AND salespm.meridiem = 'PM' 
WHERE DIRECTORY.active = 1 
GROUP BY DIRECTORY.site_id 
ORDER BY DIRECTORY.site_id ASC 
LIMIT :totalLocations 

注:此解决方案假定

  • {Site_ID, business_Date, meridiem}是唯一
  • 从未有一个PM没有AM记录的记录
  • salesPM.cover_counts - salesAM.cover_counts永不等于零
+0

@Brett - - (注意康拉德),为了得到正确的封面,你必须从封面上减去早上的封面o你知道晚上有多少食客... – DRapp 2012-03-22 17:17:58

+0

@DRapp谢谢我会更新,但我只是做了一个faceplam看Andomor的解决方案 – 2012-03-22 17:18:51

+0

我不认为这是正确的总和。第二个左连接将包含第一个左连接中每一行的重复行。 – Andomar 2012-03-22 17:33:29

1

从连接条件删除此:

AND sales.meridiem = 'AM' 

然后你可以选择:

ROUND((SUM(case when sales.meridiem = 'AM' 
       then sales.daily_sales/sales.cover_counts end)/4), 2) as AMSum 
ROUND((SUM(case when sales.meridiem = 'PM' 
       then sales.daily_sales/sales.cover_counts end)/4), 2) as PMSum 

从PM减去AM,你可以:

SUM(case sales.meridiem 
    when 'PM' then sales.daily_sales/sales.cover_counts 
    when 'AM' then - sales.daily_sales/sales.cover_counts 
    end) as am_minus_pm 
+0

它将从PM中减去AM的位置? – Brett 2012-03-22 17:20:08