Count variables in a loop - variables

I want to count the variables and show it somewhere in my code. I have a loop:
<cfloop query="get_serial">
<cfif PROCESS_ID eq attributes.action_id> #SERIAL_NO# </cfif>
</cfloop>
and its query:
<cfquery name="get_serial" datasource="#dsn3#">
SELECT *
FROM SERVICE_GUARANTY_NEW
WHERE STOCK_ID = #attributes.action_row_id#
ORDER BY SERIAL_NO
</cfquery>
Everything works fine, but I want to count how many variables are displayed exactly. I actually want to do it in this way because I lack of database variables. Actually it is possible to get the amount of these variables from database, I just don't know which variables to use. That is why I want to count it manually.

ColdFusion exposes a variable that tells you how many rows are returned in your query, without running a loop to count them:
<cfquery name="get_serial" datasource="#dsn3#">
SELECT *
FROM SERVICE_GUARANTY_NEW
WHERE STOCK_ID = #attributes.action_row_id#
ORDER BY SERIAL_NO
</cfquery>
<cfoutput>There are #get_serial.recordCount# rows.</cfoutput>
<cfoutput query="get_serial">
<p>#get_serial.serial_no#</p>
</cfoutput>

If I understand you correctly you can do it with a counter in your loop.
<cfset counter = 0 />
<cfloop query="get_serial">
<cfif PROCESS_ID eq attributes.action_id>
#SERIAL_NO#
<cfset counter ++ />
</cfif>
</cfloop>
<cfoutput>Output #counter# times!</cfoutput>
EDIT: to answer your follow up question:
<cfset counter = 0 />
<cfsavecontent variables="myContent">
<cfloop query="get_serial">
<cfif PROCESS_ID eq attributes.action_id>
#SERIAL_NO#
<cfset counter ++ />
</cfif>
</cfloop>
</cfsavecontent>
<cfoutput>
<p>Output #counter# times!</p>
<p>#myContent#</p>
</cfoutput>
Hope that helps!

Here's another couple answers, just for fun :), although having the counter is probably the best way since you're already incurring the performance hit of using the loop.
<cfquery name="getCount" dbtype="query">
SELECT PROCESS_ID FROM get_serial WHERE PROCESS_ID = #attributes.action_id#
</cfquery>
<cfset total = getCount.RecordCount />
And using lists, always fun:
<cfset total = ListValueCount(ValueList(get_serial.PROCESS_ID), attributes.action_id) />
Point being that there are a multiple ways to solve that kind of problem, so have fun :)

Related

Is it possible to run SQL query once and include both detail output and a count by category?

Is it possible run a SQL once and display the detailed output + the count of amount by name? The code below works as I wish, but it runs two queries, so this may not be so productive..
<cfquery name="myta" datasource="zett">
Select w.t_firstname, w.t_lastname, w.t_total
from table_bst a, table_zr w
where 1=1
....
</cfquery>
<cfquery name="meto" datasource="zett">
SELECT a.t_firstname as Firstname, COUNT(*) AS Status
from table_bst a, table_zr w
where 1=1
....
</cfquery>
<cfif meto.recordcount EQ 0>
<table><tr><td style="color:#FF0000">There is currently an error</td></tr></table>
<cfelse>
<cfoutput>
<table>
<cfloop query="meto">
<cfset temp = ValueList(myta.status)
<tr><td>FirstnameList: <cfoutput>#ListLen(temp)#</cfoutput></td></tr>
</table>
</cfoutput>
</cfif>
The simplest and ColdFusion-centric way of accomplishing what you are looking for is to simply use a query of query:
MAIN QUERY:
<cfquery name="myta" datasource="zett">
SELECT w.t_firstname, w.t_lastname, w.t_total
FROM table_bst a
INNER (OR LEFT/RIGHT OUTER) JOIN table_zr w ON a.? = w.?
WHERE
[
1=1 is only really useful if you have some sort of if/else logic in your
WHERE clause, and it's used to make sure there is a value there if none
of the if/else conditions are met.
]
AND/OR [other stuff]
</cfquery>
Query of Query:
<cfquery name="meto" dbtype="query">
SELECT t_firstname AS FirstName, count(*) AS Status
FROM myta
GROUP BY FirstName
</cfquery>
OUTPUT:
<table>
<cfif meto.recordcount EQ 0>
<tr><td style="color:#FF0000">There is currently an error</td></tr>
<cfelse>
<cfoutput query="meto">
<tr>
<td>#Firstname#:#Status#</td>
</tr>
</cfoutput>
</cfif>
</table>
https://trycf.com/gist/529c0bf10b7c6d7420eae399572744bb/lucee5?theme=monokai

ColdFusion count the amount without using SQL

I am trying to count the amount without using SQL count() code
Is there a way to extract the results including the number amount over ColdFusion?
Select test
From ......
Where .....
<Cfif not test.RecordCount>
No records found
</Cfif>
<cfoutput query="test">#amount#</cfoutput>
It should display like this
TEST CountOutput
TEST A: 22
TEST B: 32
TEST B: 1
TEST C: 23
(From comments ...)
Why can't you use SQL for this? Unless there's a valid reason you can't use COUNT, it's by far the simplest way to aggregate. You don't need to know the specific values in the database table in order to perform a COUNT. Just do:
SELECT column, count(*) AS someAlias
FROM tableName
GROUP BY column
Yes, it is possible to do the same in ColdFusion code, but again unless there's a specific reason to do so, it's more efficient to use SQL.
<cfset data = {} />
<cfset names = {} />
<cfloop query="test">
<cfif not structKeyExists(data, test.name)>
<cfset data[test.name] = 0 />
<!--- if you need to preserve original case of name --->
<cfset names[test.name] = test.name />
</cfif>
<cfset data[test.name] += 1 />
</cfloop>
<cfoutput>
<cfloop collection="#data#" item="key">
#names[key]#: #data[key]#<br />
</cfloop>
</cfloop>
To get the total count without using SQL, Use
QUERYVARIABLE.RECORDCOUNT
Based on the condition used in the SQL query it will give you the count.
FOR Example,
<cfquery name="test">
SELECT * FROM database WHERE name=testA
</cfquery>
<cfdump var="#test.RECORDCOUNT#" />
Use this within a function, call it and store the return value in a stack or an array.
I strongly recommend you use a SQL Count(). I cannot imagine why you would want to do it inside a CFLoop or CFOutput, but it is possible if you use the Group attribute, and count each row that way.
Did you know that after you execute CFQuery against your SQL server to get all those detail records, you can run a "query of queries" summarize the SQL data. This article seems to explain it:
https://www.quackit.com/coldfusion/tutorial/coldfusion_query_of_queries.cfm

set value with cfif cfelse Coldfusion

I'm trying to set value
If it matched the output should be renamed as "INFORMATION AVAILABLE" if not as "NO MATCH".
Thank you for your help and tricks
<cfquery name="gethi" datasource="testdb">
select resp from t_tes x where service=upper('B76Z7') and rownum <=1
and resp Like ('%OK%')
</cfquery>
<cfif gethi.resp is "">
<cfset gethi.resp="INFORMATION AVAILABLE">
<cfoutput>#gethi.resp#</cfoutput>
<cfelse>
<cfoutput>gethi.resp="NO MATCH"</cfoutput>
</cfif>
What can be done that it works as requested? any tips? thank you
It seems to me that what you are trying to accomplish is to determine whether the query returns a match or not and to display information on whether a match was found or not.
I don't see that you actually need to set a query cell. I don't see that you actually need to set any variable.
<cfquery name="MyQuery" datasource="testdb">
select resp from t_tes x where service=upper('B76Z7') and rownum <=1
and resp Like ('%OK%')
</cfquery>
<cfif MyQuery.RecordCount eq 0>
NO MATCH
<cfelse>
INFORMATION AVAILABLE
</cfif>
It is possible that you do not even have to do what you are doing here, but I do not have much information, so based on what you want:
<cfif gethi.resp is "">
<cfset gethi.resp="INFORMATION AVAILABLE">
<cfoutput>#gethi.resp#</cfoutput>
<cfelse>
<cfset gethi.resp="NO MATCH">
<cfoutput>#gethi.resp#</cfoutput>
</cfif>
I reckon that you may want to check if there is some value in gethi.resp, rather than comparing it with blank string. So maybe:
<cfif Len(gethi.resp)>
<cfset gethi.resp="INFORMATION AVAILABLE">
<cfoutput>#gethi.resp#</cfoutput>
<cfelse>
<cfset gethi.resp="NO MATCH">
<cfoutput>#gethi.resp#</cfoutput>
</cfif>

How to compare values from two separate quires but not use inner loop?

I'm working on my project where I have to compare values from DB to the values from .csv file. I have used 'cfhttp' to convert my .csv to query and then I loop over that query and another query that I used to get values from DB. Inside of those two loop I used if statements to compare my values and check if they match. Then I stored them in the lists and use those list in cfquery tags for my update. I have 14k records in DB and about the same number of records in my .csv file. My current code takes less than 2 minutes to output records from the list to the screen for testing purpose. I still did not test how long update will take. Before I run my update I would like to see if any of you would recommend any other approach for my project? Could I reduce my execution time to less than I currently have? Here is my code that I have:
<cfhttp name="records" columns="A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X" method="get" url="http://path to csv/temp.csv"/>
<cfquery name="getRecords" datasource="test">
Select s.ID, f.URID, s.UR_NUMBER, CODE, f.FIELD
From USERS s
Left Outer Join MAPS f
ON s.ID = f.URID
</cfquery>
<cfset NumA = "">
<cfset NumB = "">
<cfset NumC = "">
<cfset NumD = "">
<cfset NumE = "">
<cfset updNumD = "">
<cfset updNumE = "">
<cfloop query="records">
<cfloop query="getRecords">
<cfif records.A EQ getRecords.UR_NUMBER>
<cfif records.W NEQ getRecords.CODE>
<cfif records.W EQ 'A'>
<cfset NumA = ListAppend(NumA,"#records.A#")>
<cfelseif records.W EQ 'B'>
<cfset NumB = ListAppend(NumB,"#records.A#")>
<cfelse>
<cfset NumC = ListAppend(NumC,"#records.A#")>
</cfif>
</cfif>
<cfif getRecords.URID EQ ''>
<cfif records.W EQ 'D'>
<cfset NumD = ListAppend(NumD, "#getRecords.ID#")>
<cfelseif records.W EQ 'E'>
<cfset NumE = ListAppend(NumE, "#getRecords.ID#")>
</cfif>
<cfelse>
<cfif records.W EQ 'E'>
<cfset updNumD = ListAppend(updNumD, "#getRecords.URID#")>
<cfelseif records.W EQ 'D'>
<cfset updNumE = ListAppend(updNumE, "#getRecords.URID#")>
</cfif>
</cfif>
</cfif>
</cfloop>
</cfloop>
Here I dump my lists to the screen:
<cfdump var="#NumA#">
<cfdump var="#NumB#">
<cfdump var="#NumC#">
<br>
<cfdump var="#NumE#">
<cfdump var="#NumD#">
<br>
<cfdump var="#updNumE#">
<cfdump var="#updNumD#">
Also I was wondering if it's possible to get out with cfhttp tag just columns that I need from my .csv? Now I'm garbing all columns from my .csv even if I use only two of them column A and W. Also is it possible to join query from 'cfhttp' to my query from DB? If anyone can give me some advise on this project please let me know.
So I think you are only interested in data where records.A is equal to getRecords.UR_NUMBER. You could use a Query of Queries to get the intersection of the two datasets. Something like:
<cfquery name="intersection" dbtype="query">
select *
from records, getRecords
where records.A = getRecords.UR_NUMBER
</cfquery>
That should give you combined dataset which you can then loop through and build up your lists. As Matt Busche mentioned in the comments, list operations are slow, so arrayAppend will be faster.
If Query or Query is too slow, then you may want to look at converting one of the recordsets to a struct (of key value pairs) as look ups are faster. For example:
<cfscript>
// convert to structs as key lookups are fast
dbData = {};
for (row in getRecords) {
dbData[row.UR_NUMBER] = row;
}
csvData = {};
for (row in records) {
if (structKeyExists(dbData, row.A)) {
// we have a match, so build the lists here...
writeDump(dbData[row.A]);
}
}
</cfscript>

Build struct and then populate with the values from query?

I have task to update/insert some fields in two different tables. Before I run my update I have to grab values from my query and put them in structure where one of my values should be the key. My query looks like this:
<cfquery name="getRecords" datasource="test">
Select
s.ID
,f.USER_ID
,s.USER_NUMBER
,s.STATUS
,f.DINING
From USERS s
Left Outer Join FIELDS f ON s.ID = f.USER_ID
</cfquery>
I need USER_NUMBER to use as a key in my structure and store all other values from the query above. I will use this structure to compare values from my other list and then build final list that I will use for update/insert. I tried something like the code below, but it did not work:
Here is a stand alone example using a manual query:
<cfset getRecords = queryNew("")>
<cfset queryAddColumn(getRecords, "ID", [1,2,3])>
<cfset queryAddColumn(getRecords, "USER_ID", ["userA","userB","userC"])>
<cfset queryAddColumn(getRecords, "STATUS", ["Active","Active","Active"])>
<cfset queryAddColumn(getRecords, "DINING", ["X","Y","Z"])>
<cfset myStruct = StructNew()>
<cfloop query="getRecords">
<cfset myStruct = [key:#USER_NUMBER#{
id:#ID#
,userid:##USER_ID
,status:#STATUS#
,dining:#DINING#
}]>
</cfloop>
If anyone can help with this code please let me know. I usually use arrays but this time I have to use struct because of some other reasons. Thank you.
I believe you just need to move your key up a level so that the loop doesn't overwrite the values. so try something like:
<cfset myStruct = StructNew()>
<cfloop query="getRecords">
<cfset myStruct[getRecords.USER_ID] = {
id:getRecords.ID,
userid:getRecords.USER_ID,
status:getRecords.STATUS,
dining:getRecords.DINING
}>
</cfloop>
Then to access the variables you can use something like:
<cfoutput>#htmlEditFormat(myStruct[1].dining)#</cfoutput>