ColdFusion - Output Grouping From a Query - coldfusion

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.

Related

Why is cfoutput being ignored?

I have a very simple CFML page as follows:
<cfquery name="qry" datasource="#application.db.source#" username="#application.db.user#" password="#application.db.pass#">
SELECT * FROM changemgmt.rfc WHERE rfc_id = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="0">;
</cfquery>
<cfoutput query="qry">
#qry.RecordCount#
</cfoutput>
My <cfoutput> tag is not working as I would expect. If you were to look at the source code of this page, it would be entirely composed of empty lines. It's as if the <cfoutput> tag is being parsed out by the server. However if I change the code to:
<cfoutput>
#qry.RecordCount#
</cfoutput>
I am using Lucee as my backend CFML engine. Can anyone explain to my why there is a difference?
<cfoutput query="qry"> this is used to loop throw all the rows in the query. If your query result have no rows, the execution will never reach the login with in the <cfoutput query="qry">. But if there are 1+n rows in the result, your code will print the recordcount 1+n times.
In this case if all you want is to print recordcount of the result, then you just need to use <cfoutput>#qry#</cfoutput>
But if you want to print values each row of the query then you can use <cfoutput query="qry">
<cfoutput query="qry">
<div>
<span>#qry.rfc_id#</span>
<span>#qry.name#</span>
...
</div>
</cfoutput>

Conditional CF Record Count

I'm trying to save my database server a few requests by querying a large number of items from several categories all at once, then using <cfif ... > statements to filter those results into unique tables I'm showing for each category. I'm looking to find record counts for each of the categories returned, not just the record count of the overall query.
The basic code is:
<cfinvoke component="..." method="..." returnvariable="session.queryList">
...
</cfinvoke>
<cfoutput #session.queryList#>
<cfif #category# eq "A">
[Table for A things]
</cfif>
<cfif #category# eq "B">
[Table for B things]
</cfif>
<cfif #category# eq "C">
[Table for C things]
</cfif>
</cfoutput>
I don't want to use "ORDER BY category" here because the tables are actually on different divs we're hiding and showing, so we need separate tables.
The problem I'm running into is that I want the "Table for A Things" to say "No results" if there is no records returned where category="A", but RecordCount seems to apply to the entire query. Is there any way to say something along the lines of <cfif #queryList.RecordCount# WHERE #category# eq "A" GT "0">?
QoQ can help.
<cfinvoke component="..." method="..." returnvariable="session.queryList">
...
</cfinvoke>
<!---then run QoQ on it--->
<cfquery name="catA" dbtype="query">
select * from session.queryList where category ="A"
</query>
<cfquery name="catB" dbtype="query">
select * from session.queryList where category ="B"
</query>
<cfif catA.recordcount>
<cfoutput query="catA">
[Table for A things]
</cfoutput>
<cfelse>
No Records for A things
</cfif>
<cfif catB.recordcount>
<cfoutput query="catB">
[Table for B things]
</cfoutput>
<cfelse>
No Records for B things
</cfif>
I believe you are trying to do the following. <cfoutput> has a feature that helps you group the query results given the query is ordered by the grouping item.
<cfoutput query="#session.queryList#" group="category">
<h3>Category #category#</h3>
<table>
<tr><th>...</th><th>...</th></tr>
<cfoutput><!--- This cfoutput loops through the each record in the group. --->
---rows---
</cfoutput>
<table>
</cfoutput>
QofQ is slow. You can accomplish this with a single round trip to mySQL:
SELECT someColumn, category, count(*) AS categoryCount
FROM theTable
GROUP BY category
ORDER BY category, someColumn
Grouping will give you a count per category which you can use in CFML.
<cfoutput query="session.queryList" group="category">
<cfif categoryCount eq 0>
No Records for #category#. =(
</cfif>
<cfoutput>
#someColumn#<br>
</cfoutput>
</cfoutput>

group cfdirectory by dateLastModified (date not time)

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.

Compare mysql query to sql query

I am a lot more at home manipulating arrays and objects in php or javascript, and do next to no work with coldfusion.
I have one query pulling data from mysql. I would like to store results list or array ( or simpler approach)
WHile looping over a second query from msql that generates html output I need to see if one value is contained in prior mysql array or list.
Have tried playing with varierty of cf array/list methods and really not sure what best approach is to resolve following if.
CF version is 9
<cfquery datasource="Mysql" name="premium_submitters">
SELECT submitter_id from table
</cfquery>
<!--- Need loop to store to array or list??--->
<cfquery datasource="Sql" name="main_data">
SELECT * from table
</cfquery>
<cfoutput query="main_data">
<cfif #submiiter_id# <!---is in Mysql array/list return boolean---> >
</cfif>
</cfoutput>
Use ValueList to get the value of one column of a query into a list.
<cfquery datasource="Mysql" name="premium_submitters">
SELECT submitter_id from table
</cfquery>
<cfset submittersList = ValueList(premium_submitters.submitter_id)>
<cfquery datasource="Sql" name="main_data">
SELECT * from table
</cfquery>
<cfoutput query="main_data">
<cfif ListFind(submittersList, main_data.submitter_id) gt 0>
<!--- is in list, do whatever --->
</cfif>
</cfoutput>

can't define id ColdFusion

here is my ColdFusion code:
Example1:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = PRODUCT_CATID
</cfquery>
#get_brand.product_catid#
But it shows all the time number 1, i just can't understand why, and how do i make it work properly, this code should have defined the brand_id, but instead shows 1.
The system is Workcube.
Here is my example for getting from the static product's id, its dynamic price:
Example 2:
<cfset product_id = 630>
<cfquery name="price_standart" datasource="#dsn3#">
SELECT
PRICE_STANDART.PRICE PRICE
FROM
PRICE_STANDART
WHERE
PRICE_STANDART.PRODUCT_ID =
<cfqueryparam value="#product_id#" cfsqltype="cf_sql_integer">
</cfquery>
But this time i need to get from dynamic product's ID its dynamic brand id.
This script works the same way as the Example 1:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT BRAND_ID
FROM PRODUCT_BRANDS
WHERE BRAND_ID = BRAND_ID
</cfquery>
#get_brand.BRAND_ID#
As Andreas shows in his code, your query isn't going to work as written. The statement WHERE PRODUCT_CATID = PRODUCT_CATID doesn't actually pass a value - it would actually just be self-referential within the table values. In this case, it would return everything in the table.
You should instead have:
WHERE PRODUCT_CATID = #PRODUCT_CATID#
Where #PRODUCT_CATID# represents a variable. Better yet, use cfqueryparam as Andreas shows (this prevents SQL injection and improves query performance). However, I am not even sure that is what you intend since if you have the product ID why do you need to get it from the database? Instead, I assume you probably want to get the brands from the product in a particular category. Not knowing your table structure, it's hard to write that query for you but it might look something like:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT.BRAND_ID
FROM PRODUCT
INNER JOIN PRODUCT_CAT
ON PRODUCT.PRODUCT_CATID = PRODUCT_CAT.PRODUCT_CATID
WHERE PRODUCT_CATID = <cfqueryparam cfsqltype="cf_sql_integer" value="#product_catid#">
</cfquery>
Lastly, as both comments indicate, you would need to loop through the results to see all the records returned.
You need to wrap the statement in tags like this.
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID FROM PRODUCT_CAT WHERE PRODUCT_CATID = PRODUCT_CATID
</cfquery>
<cfoutput query =GET_Brand">
#get_brand.product_catid#
</cfoutput>
It's not very clear what your question really is about, but let me guess:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = <cfqueryparam cfsqltype="cf_sql_integer" value="#product_catid#">
</cfquery>
where #product_catid# refers to a variable you defined earlier in your code or received via form or url scope.
<cfloop query="GET_BRAND">
#get_brand.product_catid#<br />
</cfloop>
will show a list of all the product_catid's returned by the query.
It's not too clear what you are after here, but in the queries there are at least 2 problems. First your WHERE clause
WHERE PRODUCT_CATID = PRODUCT_CATID
is like saying
WHERE 1=1
This will return the full recordset. You can see this by adding
<cfdump var="#GET_BRAND#">
under your code to see the query output. I'm guessing this will show all records in the table.
To match just one record you need your WHERE clause to be like
WHERE PRODUCT_CATID = 3
or have the #...# wrapped around the variable you are trying to match to make it dynamic.
Secondly to the query result may be more than one record, and to see any more than the first record you need to loop over the output. One way is to use
<cfoutput query="GET_BRAND">
#BRAND_ID# <br>
</cfoutput>
My guess of what you are after is
<cfset ID_TO_MATCH=3>
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT BRAND_ID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = #ID_TO_MATCH#
</cfquery>
<cfoutput query="GET_BRAND">
#BRAND_ID# <br>
</cfoutput>