Как уменьшить количество запросов на каждый месяц

Я использую My Sql 5.7 и CF11. Я хочу получить общий идентификатор qTotalPrice и quoteKeyID за каждый месяц из запроса ниже. Но не полный год. Я хочу получить данные от текущего месяца до последних шести месяцев (с июля по февраль). Если нет данных за конкретный месяц, мне нужно отобразить как 0 за конкретный месяц.

<cfquery name="thisYearsQuotes" datasource="myDB">
    SELECT * , MONTH(qDateTime) as qMonth
    FROM Quotes
    INNER JOIN Accounts
    ON Quotes.aID = Accounts.aID
    WHERE Accounts.aID = <cfqueryparam value="#VNAI.aID#" cfsqltype="cf_sql_clob" maxlength="255">
    AND Quotes.qDateTime > DATE_ADD(NOW(), INTERVAL -365 DAY)
</cfquery>

Результат этого запроса  Результаты запроса

Для получения записей за каждый месяц я написал запрос, как показано ниже.

Для получения текущего месяца

<cfquery name="SalesTotalThisMonth" dbtype="query">
    SELECT SUM(qTotalPrice) as DollarTotal , COUNT(quoteKeyID) as QuoteCount
    FROM thisYearsQuotes
    WHERE qMonth = #MONTH(NOW())#
</cfquery>

Чтобы получить один месяц назад

<cfquery name="SalesTotal1MonthAgo" dbtype="query">
    SELECT SUM(qTotalPrice) as DollarTotal , COUNT(quoteKeyID) as QuoteCount
    FROM thisYearsQuotes
    WHERE qMonth = #MONTH(DateAdd("m",-1,NOW()))#
</cfquery>

Чтобы получить два месяца назад,

<cfquery name="SalesTotal2MonthAgo" dbtype="query">
    SELECT SUM(qTotalPrice) as DollarTotal , COUNT(quoteKeyID) as QuoteCount
    FROM thisYearsQuotes
    WHERE qMonth = #MONTH(DateAdd("m",-2,NOW()))#
</cfquery>

и т. д. Как мудрый я должен получить последние шесть месяцев. Поэтому я написал несколько запросов на каждый месяц.

Есть ли возможность уменьшить код?


person Kannan.P    schedule 31.07.2018    source источник
comment
Вы пытаетесь вернуть разовый итог за последние 12 месяцев. Бывший. 750 долларов - или вы хотите получить индивидуальные итоги за каждый за последние 12 месяцев. Бывший. Январь 2018 - 200 долларов, февраль 2018 - всего 175 долларов, март - всего 375 долларов и т. Д.   -  person SOS    schedule 31.07.2018
comment
В стороне, тип данных столбца, вероятно, не cf_sql_clob, и обычно рекомендуется включать год и месяц, чтобы различать в случае перекрытия периодов времени (хотя здесь их не будет ...).   -  person SOS    schedule 31.07.2018
comment
@Ageax. да. Но не полный год. Я хочу получить данные от текущего месяца до последних шести месяцев (с июля по февраль). Если нет данных за конкретный месяц, мне нужно отобразить как 0 за конкретный месяц.   -  person Kannan.P    schedule 31.07.2018
comment
Хорошо, см. Мой ответ ниже.   -  person SOS    schedule 31.07.2018


Ответы (2)


ОБНОВЛЕНИЕ

Решением будет создание запроса на все нужные вам месяцы, а затем использование левого соединения.

SELECT 8 AS monthNum UNION SELECT 7 AS m UNION SELECT 6 AS m UNION SELECT 5 AS m UNION SELECT 4 AS m UNION SELECT 3 AS m

Чтобы сделать его автоматизированным, я добавил немного кода CF для создания вышеуказанного запроса.

<cfset today=now()>
<cfset start = 0>
<cfset numberOfMonths = 6>
<cfset listOfMonths = ''>
<cfloop condition="numberOfMonths+start GT 0">
  <cfset listOfMonths = listappend(listOfMonths, ' SELECT ' & Month(DateAdd('m', start, today)) & ' AS m ')>
  <cfset start-->
</cfloop>
<cfoutput>
<cfquery>
  SELECT SUM(O.order_Total) AS totalOrder, COUNT(O.order_ID) AS numOrders, MONTH(O.order_Date) AS qMonth
  FROM tbl_orders O 
    RIGHT JOIN (
      #ListChangeDelims(listOfMonths, 'UNION')#
    ) monthList ON monthList.m = MONTH(O.order_Date) AND O.order_Date > DATE_ADD(NOW(), INTERVAL -6 MONTH)
  GROUP BY qMonth;
</cfquery>
<cfoutput>

НАЧАЛЬНЫЙ

Я думаю, вы можете сделать это в одном запросе с правильным group by.

<cfquery name="thisYearsQuotesPerMonth" datasource="mySQL_MILESTONEBMDB">
    SELECT 
      SUM(qTotalPrice) AS DollarTotal, COUNT(quoteKeyID) AS QuoteCount, MONTH(qDateTime) as qMonth
    FROM 
      Quotes
      INNER JOIN Accounts ON Quotes.aID = Accounts.aID
    WHERE 
      Accounts.aID = <cfqueryparam value="#VNAI.aID#" cfsqltype="cf_sql_clob" maxlength="255">
      AND Quotes.qDateTime > DATE_ADD(NOW(), INTERVAL -6 MONTH)
    GROUP BY qMonth
</cfquery>
person rrk    schedule 31.07.2018
comment
Он возвращает те месяцы, которые имеют значения один год. Я хочу получить последние шесть месяцев текущего месяца. Если в месяце есть данные, тогда он должен быть рассчитан как итог, как вы упомянули выше, если в месяце нет записей, тогда он должен отображаться как 0 в запросе. - person Kannan.P; 31.07.2018
comment
Группа by вернет только тот месяц, в котором есть записи в БД. Но я хочу вернуться за последние шесть месяцев, независимо от того, есть записи или нет. Надеюсь, вы понимаете мой сценарий. - person Kannan.P; 31.07.2018
comment
Итак, я написал в качестве 1-го подзапроса как WHERE qMonth = #MONTH (NOW ()) # 2-й подзапрос как WHERE qMonth = #MONTH (DateAdd (m, -2, NOW ())) # 3-й подзапрос как WHERE qMonth = #MONTH (DateAdd (m, -3, NOW ())) # и т. д. до WHERE qMonth = #MONTH (DateAdd (m, -5, NOW ())) #. Поэтому я хочу максимально улучшить свой запрос. Заранее спасибо . - person Kannan.P; 31.07.2018
comment
@ Kannan.P Я обновил свой ответ с некоторыми изменениями. Проверь это. Запрос вернет строку за каждый месяц, даже если за этот месяц не было записей. - person rrk; 01.08.2018
comment
Это работает, хотя, если это более чем для одного запроса, я бы снова порекомендовал календарную таблицу. Это одноразовая настройка, которая очень полезна для отчетности. Мы используем их в большинстве наших баз данных. (Побочная шутка - RRK - RIGHT JOIN? Ооо, мои глаза, мои глаза! ;-) - person SOS; 01.08.2018
comment
Таблица календаря @Ageax звучит как хорошая идея. Также правое присоединение: D LOL - person rrk; 01.08.2018
comment
Я получил решение с правильным соединением, но без использования таблицы календаря. Я разместил свой запрос здесь. Спасибо за время @RRK. - person Kannan.P; 03.08.2018

Я получил решение, добавив имя главной таблицы как отчетные месяцы. Которые имеют данные из 12 строк с последним одним годом в столбцах месяца и года. Так что добейтесь этого, правильно соединив эту таблицу с моим запросом. Итак, теперь я могу получать записи за последние шесть месяцев, используя LIMIT 6.

SELECT RP.ReportYear AS `year`, RP.ReportMonth AS `month`, A.DollarTotal, A.QuoteCount
    FROM
        (   
            SELECT
                YEAR(qDateTime) AS qYear, MONTH(qDateTime) AS qMonth,
                SUM(qTotalPrice) AS DollarTotal , COUNT(quoteKeyID) AS QuoteCount
            FROM Accounts A
                INNER JOIN Quotes Q ON A.aID = Q.aID
            WHERE A.aID = 216
            GROUP BY YEAR(qDateTime), MONTH(qDateTime)
        ) A
    RIGHT JOIN ReportMonths RP ON  RP.ReportYear = qYear 
    AND  RP.ReportMonth =  qMonth 
    ORDER BY `year` DESC, `month` DESC LIMIT 6
person Kannan.P    schedule 03.08.2018
comment
Да, это вариант концепции календарного стола. Единственная проблема, связанная с использованием только месяцев, заключается в том, что если нет данных за определенные периоды, порядок результатов будет отключен, потому что значение year будет нулевым. Например, если текущий месяц - март, порядок может быть не таким (10 октября, 11 ноября, 12 декабря, 01 января, 2 февраля, 03 марта) Не уверен, имеет ли это значение в вашем случае. - person SOS; 06.08.2018