group cfdirectory by dateLastModified (date not time) - coldfusion

I am running ColdFusion 9 and Oracle database. I am trying to group all files from a directory by the dateLastModified using:
<cfdirectory action="LIST"
directory="#path_to_files#"
name="res"
sort="datelastmodified desc,name ASC"
filter="#filters#">
For example:
Date of File 1: 2016-10-03 11:49:00 am
Date of File 2: 2016-10-03 07:49:00 am
Date of File 3: 2016-08-03 07:49:00 am
File 1 & 2 should be group 1 and File 3 should be group 2
If I use a query of query, how can I compare the date based on days not time? This is what I have so far but it does not seem to work. I get no records.
<cfquery name="getfiles" dbtype="query">
SELECT name, datelastmodified
FROM res
WHERE CAST( [datelastmodified] as date) = CAST(<cfqueryparam cfsqltype="CF_SQL_DATE" value="#d#"/> as date)
</cfquery>
Does anyone know a different method to group files based on days not time?

method to group files based on days not time
To group by Date (only), add the "date only" column to your SELECT list. Then ORDER BY the new column:
<cfquery name="qSortedFiles" dbtype="query">
SELECT CAST(DateLastModified AS Date) AS DateOnly
, Name
, DateLastModified
FROM getFiles
ORDER BY DateOnly
</cfquery>
<cfoutput query="qSortedFiles" group="DateOnly">
#DateOnly#<br>
<cfoutput>
- #DateLastModified#<br>
</cfoutput>
</cfoutput>
I get no records.
FWIW, the reason is that despite using CAST ... as Date, apparently CF still preserves the "time" portion internally. So the WHERE clause is still comparing apples and oranges:
<!--- comparing Date and Time to Date (only)
WHERE 2016-08-03 07:49:00 am = 2016-08-03 00:00:00 am
Instead of using an equals comparison, use this approach:
WHERE DateLastModified >= {TheStartDateAtMidnight}
AND DateLastModified < {TheNextDayAtMidnight}
This type of comparison is more flexible as it works with both date and time columns - and dates (only).
WHERE CAST(DateLastModified AS Date) >= <cfqueryparam value="#someDate#" cfsqltype="cf_sql_date">
AND CAST(DateLastModified AS Date) < <cfqueryparam value="#dateAdd('d', 1, someDate)#" cfsqltype="cf_sql_date">

Step 1 - Use cfdirectory to get a query object.
Step 2 - Add a column using queryaddcolumn.
Step 3 - Loop through the query. Use querySetCell and dateformat on your new column
Step 4 - use cfoutput, group by your new column, to do what you need to do. Your cfdirectory tag already has the data sorted.

So I figured it out. Thanks to #Dan and #Leigh for their suggestion. I used both as guides to get what I wanted.
I used cfdirectory to get a query object.
I created a new query using QueryNew, QueryAddRow and QuerySetCell.
On the columns of the new query contained the formatted date (mm/dd/yyyy). Make sure that you declare the column as varchar not date when setting the column names QueryNew.
I used cfloop and group option and cfoutput to display the records.
<cfset path_to_files = "d:\inetpub\wwwroot\mailrideli\webrpt\">
<cfset filters = "*.pdf|*.txt|*.xls">
<cfdirectory action="LIST" directory="#path_to_files#" name="res" sort="datelastmodified desc,name ASC" filter="#filters#">
<cfset q = QueryNew("Name,dateformated,datelastmodified, size","Varchar, Varchar, date, varchar")>
<cfset count = 1>
<cfset newRow = QueryAddRow(q,res.recordCount)>
<cfloop query="res">
<cfset d = DateFormat(res.dateLastModified,"mm/dd/yyyy")>
<cfset temp = QuerySetCell(q, "Name", "#res.name#", count)>
<cfset temp = QuerySetCell(q, "dateformated", "#d#", count)>
<cfset temp = QuerySetCell(q, "datelastmodified", "#res.datelastmodified#", count)>
<cfset temp = QuerySetCell(q, "size", "#res.size#", count)>
<cfset count += 1>
</cfloop>
<cfoutput>
<cfloop query="q" group="dateformated">
#q.dateformated#<br />
<table>
<tr>
<th>File Name</th>
<th>Size (bytes)</th>
<th>Last Modified</th>
</tr>
<cfloop>
<tr>
<td>#q.name#</td>
<td>#q.size#</td>
<td>#dateformat(q.dateLastModified, 'mm/dd/yyyy')# #timeformat(q.dateLastModified, 'hh:mm:ssTT')#</td>
</tr>
</cfloop>
</table>
</cfloop>
</cfoutput>
I hope it helps anyone out there.

Related

ColdFusion - Output Grouping From a Query

I have a great question that is probably bone-head simple. I have the following query:
<cfquery name="getempareview" dbtype="query">
SELECT firstname,lastname,deptname,supcode
FROM getreviews
WHERE supcode IN (#preserveSingleQuotes(setsupcode)#)
</cfquery>
What I need to do is output so that the supcode has the other data under it in a list. So, if I have 100 rows of data and the supcode is the same on 25 of the records, just have the following:
supcode
firstname lastname - deptname (all 25 records would be listed out here)
Any help would be greatly appreciated.
Nested outputs. Try this.
<cfoutput query="YourQueryName" group="SupCode">
<h2>#SupCode#</h2>
<cfoutput>
#FirstName# #LastName# <br/>
</cfoutput>
</cfoutput>
You need to use nested and grouped output. And add an ORDER BY to your query.
<cfset setsupcode = "1,3,5">
<cfquery name="getempareview" dbtype="query">
SELECT firstname,lastname,deptname,supcode
FROM getreviews
WHERE supcode IN (<cfqueryparam value="#setsupcode#" cfsqltype="numeric" list="yes">)
ORDER BY supcode, deptname, lastname, firstname
</cfquery>
<cfoutput query="getempareview" group="supcode">
<h2>#supcode#</h2>
<cfoutput group="deptname">
#firstname# #lastname# (#deptname#) <br>
</cfoutput>
</cfoutput>
https://trycf.com/gist/763ede5485b0978504250f7f5baf9deb/acf11?theme=solarized_dark
Also, since this is apparently a Query of Query, you may be able to better organize your data in your initial query, rather than having to come back to reprocess the data.

ColdFusion Dates before a date

I seem to have a brain fart here. I'm trying to show all users that were entered in a database 14 days, or more, before today's date. For some reason I either get everyone or no one, but not the ones I need. Here is what I have. Please tell me where I am going wrong. Thank You!
<CFSET TodaysDate = #DateFormat (Now(), "mm-dd-yyyy")#>
<CFSET CheckDate = #DateFormat(TodaysDate-14,"mm-dd-yyyy")#>
<cfquery name="getUser" datasource="DNS_Test">
select *
from Login
where DateEntered <= #CheckDate#
</cfquery>
<cfoutput>
<cfloop QUERY="getUser">
#getUser.LastName#, #getUser.FirstName# <br>
<cfloop>
</cfoutput>
You'll want to use DateAdd().
Example: Never use select *, instead use column names... also investigate using <cfqueryparam>
SELECT LastName, FirstName
FROM Login
WHERE DateEntered <= <cfqueryparam value="#DateAdd( 'd', -14, now() )#" CFSQLType="CF_SQL_DATE">
You may also want to do the calculation in SQL. For example, in SQL Server:
SELECT LastName, FirstName
FROM Login
WHERE DateEntered <= CONVERT(date,
DateAdd(dd, <cfqueryparam value="-14" CFSQLType="CF_SQL_INTEGER">,
getDate())
)
Some adjustments may be needed if DateEntered has hh:mm:ss

How to compare a string from a query results?

I want to get the total number of records that a column has for a string.
For example, seller column = 'ONA'. I want to know how many records are equal to "ONA" and how many are not.
This is what I have:
<cfset stringONA= "ONA">
<CFSET onaseller= 0>
<CFSET notseller=0>
<cfloop query="getunion_again">
<cfif #getunion_again.seller# eq stringONA>
<cfset onaseller = onaseller +1 >
<P>TEST</P>
<cfelse>
<cfset notseller = notseller +1>
</cfif>
</cfloop>
<cfdump var=#onaseller #>
<cfdump var=#notseller #>
I'm not getting any errors, just not getting any count.
Wouldn't it just be easier to do a query-of-query to get the number of records that match your criteria without looping?
<cfquery name="qryCount" dbtype="query">
SELECT COUNT(*) AS positive_count
FROM getunion_again
WHERE seller = <cfqueryparam cfsqltype="cf_sql_varchar" value="#stringONA#">
</cfquery>
<cfset onaseller = qryCount.positive_count>
<cfset notseller = getunion_again.recordcount - onaseller>
One can use listValueCountNoCase() to count the matches in a list, and one can use valueList() to extract a query column as a list. And the number of mismatches is the number of rows less the number of matches.
So:
values = valueList(getunion_again.seller);
onaseller = listValueCountNoCase(values, stringONA);
notseller = getunion_again.recordCount - onaseller;

How can we add a new row in middle of a cfquery result?

I have a query result set from cfquery. I just want to add a new after a particular row number. But When tried each time it inserts the row at the end.
Is there any way I can insert row at the middle of the query?
<cfquery datasource="cse" name="abc">
select * from grade
</cfquery>
<cfset i = 0>
<cfloop query="abc">
<cfset i = i+1>
<cfif i eq 2>
<cfset queryAddRow(abc)>
</cfif>
</cfloop>
You cannot, easily. You have a coupla options.
<cfquery name="resultSet" dbtype="query">
SELECT col1, col2, etc
FROM yourQuery
WHERE [somecondition matching the "top" rows]
UNION
SELECT 'value' AS col1, 'value' AS col2, etc
UNION
SELECT col1, col2, etc
FROM yourQuery
WHERE [somecondition matching the "bottom" rows]
</cfquery>
Or you could simply loop over the original query, building a new query, using queryNew(), queryAddRow() and querySetCell(). At the appropriate point in the loop... add the row you want to insert, then continue adding the rest of them.
There's no elegant way I can think of.
Not knowing the goal you are trying to accomplish, my first advice would be along the lines of the other answers. Add rows that you can subsequently sort using Order By. However, if you really just want to inject a row at a specific position in the existing query, this should do it for you. Note you'll need to define the columns in the QueryNew(), so I've provided a sample case.
<cfquery datasource="cse" name="abc">
select student, teacher from grade
</cfquery>
<cfset abc_new = QueryNew("student,teacher","varchar,varchar")>
<cfloop query="abc">
<!--- ADD NEW DATA TO QUERY AT ROW 2 --->
<cfif CURRENTROW eq 2>
<cfset QueryAddRow(abc_new) />
<cfset QuerySetCell(abc_new,"STUDENT","Tommy Oliver") />
<cfset QuerySetCell(abc_new,"TEACHER","Ms. Appleby") />
</cfif>
<!--- COPY ORIGINAL DATA TO QUERY, ROW NUMBERS NOT PRESERVED --->
<cfset QueryAddRow(abc_new) />
<cfset QuerySetCell(abc_new,"STUDENT",abc.STUDENT) />
<cfset QuerySetCell(abc_new,"TEACHER",abc.TEACHER) />
</cfloop>
<cfdump var="#abc_new#">
The best way would be to create a new query, copying each row from the original but adding the new row at the required point.
Use QueryNew( ) to create the new query.
A bit like copying text files line-by-line and inserting a new line in the middle!
Again, not quite sure you'd need to do this - you could simply add a sortorder column, incrementing in 10s for each row. The new row would then have a sortorder in between the row before and the row after. eg sortorder would be 15 to insert between 10 and 20.
Hope this helps!
I assume row positions in your recordset are based on what you ORDER BY'd in your initial CFQUERY.
Therefore, I'd add the row to the recordset, then do a query of that recordset (query of query) using the same ORDER BY as the initial query, which should then return all rows including your new one, in the (presumed) proper order, in a new recordset.

ColdFusion Date Logic

I am embarrassed to admit that I am not the greatest when it comes to dates and date logic ColdFusion.
<!---checks frequency for form schedule and sets datepart. RecordType_Frequency is a column in database daily, weekly, monthly etc.--->
<CFSWITCH expression="#RecordType_Frequency#">
<CFCASE value="Daily">
<CFSET datepart = "d">
</CFCASE>
<CFCASE value="Weekly">
<CFSET datepart = "ww">
</CFCASE>
<CFCASE value="Monthly">
<CFSET datepart = "m">
</CFCASE>
<CFCASE value="Quarterly">
<CFSET datepart = "q">
</CFCASE>
<CFCASE value="Yearly">
<CFSET datepart = "yyyy">
</CFCASE>
</CFSWITCH>
<!---setting dates based on database values for when the form should schedule--->
<!---enddate Uses the RecordType_Frequency_StartDate column from the database which is a date in the past. Coefficient is a stored db value for the frequency 1,2 etc. for could scheduled every 1 year, 2 year --->
<cfset enddate = datediff(datepart,RecordType_Frequency_StartDate,todaydate) + Coefficient>
<!---start date is set to current RecordType_Frequency_StartDate which is a column value from the database--->
<cfset startdate = RecordType_Frequency_StartDate>
<!---sets the next start date for when the for should schedule based on historic db start date--->
<cfset new_date = dateformat(DateADD(datepart,Coefficient,startdate),'MM-DD-YYYY')>
<cfloop from="1" to="#enddate#" index="i">
<cfset new_date = dateformat(DateADD(datepart,Coefficient,startdate),'MM-DD-YYYY')>
<cfset startdate = new_date>
<cfset diff = datediff(datepart,RecordType_Frequency_StartDate,startdate)>
<cfif (startdate GT todaydate)>
<cfset next_date= startdate>
<cfoutput>
<!---I need this output to equal the next date value that would fall based on the schedule, future date. I am seeing multiple dates and need to figure out how to capture would weould truly be the next scheduled date--->
Next Date = #diff# - #dateformat(next_date)#<br />
</cfoutput>
</cfif>
</cfloop>
In summary, I have forms that are on a schedule. The start/set up date is the only date that I have to use. I need to to grab or populate the next scheduled date for the form using what information I have. Obviously the next creation date needs to fall in the future as this date will be used in conjunction with a scheduled event.
I have posted the code with comments and need help grabbing the next logical date closest to the current date that should fall in sequence.
http://cfquickdocs.com/#DateAdd
If all you need is the next possible date, use the dateadd() function.
For example, if you want the next weekday use: dateadd("w", 1, now())
Assuming I understand your problem, then a UDF that I wrote a while back might solve your problem:
http://www.bryantwebconsulting.com/blog/index.cfm/2011/2/24/EnglinshFriendly-Interval-Calculation
Among several other options for the "interval" argument, it should also accept the ones you use in your switch block.