MySQL查询-两行之间的差异


MySQL query - Difference between two rows

我需要一些关于查询的头脑风暴帮助。我有一张销售表,每个餐厅(每天)有两排。一行是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实现这一点,但我只是好奇如何在查询中实现这一目标。如有任何帮助或见解,我们将不胜感激。如果需要更多的细节,请告诉我。

可以再次加入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从不等于零

将其从联接条件中删除:

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