SQL tricks rather than a coldfusion loop
Im a speed freak. Thats why I try to structure my SQL statements in such a way that I can just have Coldfusion loop and output them, without any Query of Queries, swapping data to arrays, or other such nonsense. Today, I needed to return a query object that would find any auctions in a given date range for a calendar display. My problem was, I wanted each company (4 companies) to return 1 record per day that would show the number of auctions on that day, even if the day had no auctions at all. I know I could have done my auction query grouped by date, then looped a month and QoQ back to my auction result, but thats messy!
I could even have made a table containing every date for the next 20 years and joined too it, but that seems too manual to me.
Here is what I came up with. This uses recursion to create a recordset with each date in my requested range, then joins to the recordset in memory. How cool is that? Its zippy fast, and super easy to do a grouped output with. Here is the SQL, hope it helps someone!
/* Declare start and ending dates */
DECLARE @startDate as datetime
SET @startDate = <cfqueryparam cfsqltype="cf_sql_date" value="#startDate#" />
DECLARE @endDate as datetime
SET @endDate = <cfqueryparam cfsqltype="cf_sql_date" value="#endDate#" />
/* Build temp table of days in my range */
;WITH DayList (DayDate) AS
(
SELECT @startDate
UNION ALL
SELECT DATEADD(d, 1, DayDate)
FROM DayList
WHERE (DayDate < @endDate)
)
/* Grab the days and sub-query for auction count */
SELECT
A.DayDate as AuctionDate,
B.Name as Company,
B.Url as CompanyURL,
(SELECT
Count(*)
FROM
auction
WHERE
companyID = B.ID
AND active = 1
AND deleted = 0
/* necessary to do this so that the times dont mess up the comparison */
AND CAST(FLOOR(CAST( startDate AS float)) AS datetime) = A.dayDate
) as AuctionCount
FROM
dayList A, Company B
ORDER BY AuctionDate ASC