简体   繁体   English

MySQL查询 - 两行之间的差异

[英]MySQL query - Difference between two rows

I need a little help brainstorming on a query. 我需要一些帮助头脑风暴的查询。 I have a sales table that has two rows (per day) for each restaurant location. 我有一个销售表,每个餐厅位置有两行(每天)。 One row is AM sales, and the other is PM sales. 一行是AM销售,另一行是PM销售。 The AM sales is literally just the AM sales, however, the PM sales is a combination of the AM sales and the PM sales. AM销售实际上只是AM销售,然而,PM销售是AM销售和PM销售的组合。 So in order to extract the PM sales, you have to subtract the AM sales row from it. 因此,为了提取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       |
---------------------------------------------------------

I have a query to calculate the projected lunch per person average (which are from the AM sales), and it works great. 我有一个查询来计算每人平均预计的午餐(来自AM销售),并且效果很好。 It basically extracts the first four weeks, from the last 6 weeks of sales data, and averages them. 它基本上从过去6周的销售数据中提取前四周,并对它们进行平均。 (Note: Per person average is calculated by dividing sales by covers). (注:每人平均数是按销售额除以销售额计算得出的)。

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

Now I want to calculate the dinner per person average. 现在我想计算每人平均晚餐。 In order to do this, I would have to subtract the AM sales and covers from the PM sales and covers, respectively, before any of the math takes place. 为了做到这一点,在进行任何数学计算之前,我必须分别从PM销售和封面中减去AM销售和保险。 Is there a somewhat simple way to implement this all into one query? 是否有一种简单的方法将所有这些实现到一个查询中? I can obviously do this with PHP, but I'm just curious as to how this can be accomplished in a query. 我显然可以用PHP做到这一点,但我只是好奇如何在查询中实现这一点。 Any help or insight would be greatly appreciated. 任何帮助或见解将不胜感激。 Please let me know if any more detail is needed. 如果需要更多细节,请告诉我。

You could do to join to t_sales again and then filter for 'PM' 可以再次加入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

Note: this solution assumes that 注意:此解决方案假定

  • {Site_ID, business_Date, meridiem} is unique {Site_ID, business_Date, meridiem}是唯一的
  • there's never a PM record without an AM record 如果没有AM记录,就永远不会有PM记录
  • salesPM.cover_counts - salesAM.cover_counts never equals zero salesPM.cover_counts - salesAM.cover_counts永远不会等于零

Remove this from the join condition: 从连接条件中删除它:

AND sales.meridiem = 'AM'

Then you can select: 然后你可以选择:

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

To subtract AM from PM, you could: 要从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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM