MySQL查询 - 两行之间的差异

时间:2012-03-22 17:04:06

标签: php mysql sql pdo

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

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

现在我想计算每人平均晚餐。为了做到这一点,在进行任何数学计算之前,我必须分别从PM销售和封面中减去AM销售和保险。是否有一种简单的方法将所有这些实现到一个查询中?我显然可以用PHP做到这一点,但我只是好奇如何在查询中实现这一点。任何帮助或见解将不胜感激。如果需要更多细节,请告诉我。

2 个答案:

答案 0 :(得分: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}是唯一的
  • 从来没有没有AM记录的PM记录
  • salesPM.cover_counts - salesAM.cover_counts永远不等于零

答案 1 :(得分: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