MySQL查询 - 两行之间的差异
问题描述:
我需要一个帮助头脑风暴的查询。我有一个销售表,每个餐厅位置有两行(每天)。一行是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来做到这一点,但我只是很好奇这是如何在查询中完成的。任何帮助或见解将不胜感激。请让我知道是否需要更多细节。
答
您可以做重新加入到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永不等于零
答
从连接条件删除此:
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
@Brett - - (注意康拉德),为了得到正确的封面,你必须从封面上减去早上的封面o你知道晚上有多少食客... – DRapp 2012-03-22 17:17:58
@DRapp谢谢我会更新,但我只是做了一个faceplam看Andomor的解决方案 – 2012-03-22 17:18:51
我不认为这是正确的总和。第二个左连接将包含第一个左连接中每一行的重复行。 – Andomar 2012-03-22 17:33:29