MySQL запрос - разница между двумя строками - PullRequest
1 голос
/ 22 марта 2012

Мне нужна небольшая помощь для мозгового штурма по запросу. У меня есть таблица продаж, которая имеет две строки (в день) для каждого местоположения ресторана. Одна строка - продажи 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);

Теперь я хочу посчитать обед на человека в среднем. Чтобы сделать это, я должен был бы вычесть продажи AM и покрытия из продаж PM и покрытия, соответственно, прежде чем какая-либо математика будет иметь место. Есть ли несколько простой способ реализовать все это в одном запросе? Очевидно, я могу сделать это с помощью PHP, но мне просто любопытно, как это можно сделать в запросе. Любая помощь или понимание будет принята с благодарностью. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Ответы [ 2 ]

2 голосов
/ 22 марта 2012

Вы можете сделать, чтобы снова присоединиться к 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 никогда не равняется нулю
1 голос
/ 22 марта 2012

Удалить это из условия соединения:

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

Чтобы вычесть AM из PM, вы можете:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...