2014-10-24 1 views
0

У меня есть таблица с суммами и созданными датами. Я хочу создать запрос, который петли - и изменяет дату в запросе. В противном случае я должен сделать это вручную.Использование ColdFusion Loops для изменения фильтра запросов базы данных

Текущий запрос:

<cfquery name=qWeekly datasource="#DSN#"> 
    SELECT SUM(Amount) 
    FROM Transactions 
    WHERE (CreatedDate BETWEEN '1-19-2014' AND '1-25-2014') 
    AND (Amount > 0) 
</cfquery> 

Я бы вручную изменить фильтр ... (CreatedDate BETWEEN '1-19-22014' AND '1-25-2014')..., затем вручную изменить его снова: (CreatedDate ...BETWEEN '1-26-2014' AND '2-8-2014').

Что я хочу сделать, это что-то вроде Between 'X' AND 'X+7', так что я получаю данные за одну неделю, увеличиваясь на 7 дней, поэтому я могу генерировать вывод по недельным диапазонам дат. В коде psuedo, что-то вроде этого:

<cfif CreatedDate < Now()> 
    <cfloop index="x" step="7"> 
     <cfquery name=qWeekly datasource="#DSN#"> 
      SELECT SUM(Amount) 
      FROM Transactions 
      WHERE (CreatedDate BETWEEN 'x' AND 'x+7') 
      AND (Amount > 0) 
     </cfquery> 
    </cfloop> 
</cfif> 

Возможно ли это?

ответ

1

Вы не говоря уже о ваших DBMS (всегда хорошо, чтобы включить его с SQL вопросов), но это возможно, вы могли бы достичь цель без цикла. Например, в SQL Server вы можете использовать CTE для создания таблицы дат начала недели. Затем присоедините его к таблице транзакций и суммируйте суммы за неделю.

SQLFiddle

<!--- Example: generate a range of 7 weeks ---> 
<cfset firstSunday = createDate(2014,1,19)> 
<cfset lastSunday = dateAdd("ww", 7, firstSunday) 
... 

<!--- Calculate totals for all weeks in range ---> 
<cfquery name="getTotalsByWeek" ...> 
;WITH ranges (WeekStartDate) AS (
    SELECT <cfqueryparam value="#firstSunday#" cfsqltype="cf_sql_date"> AS WeekStartDate 
    UNION ALL   
    SELECT DATEADD(d, 7, WeekStartDate) 
    FROM ranges 
    WHERE <cfqueryparam value="#lastSunday#" cfsqltype="cf_sql_date"> > WeekStartDate 
) 
SELECT r.WeekStartDate, SUM(t.Amount) AS TotalAmount 
FROM ranges r LEFT JOIN Transactions t 
      <!--- CreatedDate falls within 7 days of the start date ---> 
      ON t.CreatedDate >= r.WeekStartDate 
      AND t.CreatedDate < DATEADD(d, 8, r.WeekStartDate) 
GROUP BY r.WeekStartDate 
ORDER BY r.WeekStartDate 
</cfquery> 

Результаты:

2014-01-19 00:00:00.000 | 1915.74 
2014-01-26 00:00:00.000 | 567.00 
2014-02-02 00:00:00.000 | 1250.00 
2014-02-09 00:00:00.000 | NULL 
2014-02-16 00:00:00.000 | 300.00 
2014-02-23 00:00:00.000 | NULL 
2014-03-02 00:00:00.000 | NULL 
2014-03-09 00:00:00.000 | NULL 

NB: Запрос выше использует специальную конструкцию для даты сравнения, которые будут работать независимо от того, содержит ли столбец CreatedDate дата (только) или дата и время.

col >= startDateAtMidnight AND 
    col < dayAfterEndDateAtMidnight 
+0

отлично, тем более, что я забыл параметр в своем исходном запросе .. Спасибо. –

0

Что-то вроде этого:

<Cfset datePlaceholder= now()/> 


<!--- this would loop for 12 weeks ---> 
<Cfloop from="7*12" to="1" step="-7" index="stepper"> 
<cfquery...> 
    SELECT SUM(Amount) 
    FROM Transactions 
    WHERE (CreatedDate 
       BETWEEN #dateformat(datePlaceholder,'MM-DD-YYYY')# 
       AND #dateformat(dateAdd('d',stepper,datePlaceholder),'MM-DD-YYYY')#) 
    AND (Amount > 0) 
</cfquery> 

...do whatever you need to with this week of data 
</cfloop> 

Cavaets - некоторые типы полей даты включают время (smalldatetime, например), так что вы, возможно, потребуется добавить или 00:00:00 23:59:59 к ним.

Вам придется отлаживать этот код - я его не запускал.

Cfquery является одним из тех мест, где я предпочитаю тег для чтения (и вырезания и вставки из анализатора запросов или навигатора или что-то еще).

+0

im сравнение двух решений - один выше, и это выглядит чище - больше CF, чем SQL. THunk you –

+0

@AaronBirnbaum - SQL на самом деле лучший инструмент для этой задачи ;-) Запрос в цикле, как известно, неэффективен. – Leigh

0

Я бы сделал что-то похожее на Марка, но с параметризованными значениями.

<Cfset datePlaceholder= now()/> 


<!--- this would loop for 12 weeks ---> 
<Cfloop from="7*12" to="1" step="-7" index="stepper"> 
    <cfquery...> 
     DECLARE @datePlaceholder date = <cfqueryparam cfsqltype="CF_SQL_date" value="#datePlaceholder#"> 
     DECLARE @stepper tinyint = <cfqueryparam cfsqltype="CF_SQL_tinyint" value="#stepper#"> 

     SELECT SUM(Amount) 
     FROM Transactions 
     WHERE CreatedDate BETWEEN @placeholder AND DateAdd(d, @stepper, @placeholder) 
     AND (Amount > 0) 
    </cfquery> 

    ...do whatever you need to with this week of data 
</cfloop> 

Обратите внимание, что функция DateAdd в SQL немного отличается DateAdd в ColdFusion

+0

Я вижу, что вы сделали. Также хороший ответ. Спасибо. –

+0

Конечно - да, CFQUERYPARAM всегда .... –

Смежные вопросы