set value with cfif cfelse Coldfusion - sql

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>

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

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>

Count variables in a loop

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 :)

SQL Array being returned as number, not String in ColdFusion

In Coldfusion, I'm using a cfc that binds one select box to another (basically, choose a State from one box, the second box is populated with County names.) The value for the County box is a 5-digit number WHICH IS FORMATTED AS TEXT (ie. the value comes from a text field.)
The problem is that I'm finding that if the value of the selected county id starts with a '0', it's been cut off.
So I get stuff like:
ID County
11223 A
2300 B (should be 02300)
Can someone help make sure that leading 0s are not cut off?
Here's the select boxes on the page:
<!--- State Name options --->
<b>State:</b><br />
<cfselect bind="cfc:states.getStates()" bindonload="true" name="search_state" id="search_state" value="StateUSAbb" display="StateName">
</cfselect><br />
<!--- County Name options --->
<b>County:</b><br />
<cfselect bind="cfc:states.getCounties({search_state})" name="search_county" id="search_county" value="FIPS_County" display="CountyName">
</cfselect>
I hate pasting the whole .cfc but pay attention to the latter part, particularly the cfloop which uses a cfset to populate array RESULT:
<cfcomponent output="false">
<!--- Get array of media types --->
<cffunction name="getStates" access="remote" returnType="array">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!--- Get data --->
<cfquery name="data" datasource="bridges">
SELECT DISTINCT tblLoc.StateUSAbb, lkuState.StateName
FROM lkuState INNER JOIN tblLoc ON lkuState.FIPS_State = tblLoc.FIPS_State
WHERE (lkuState.StateName <> 'New Brunswick')
UNION
SELECT '' AS StateUSAbb, ' ALL' AS StateName
FROM lkuState
ORDER BY StateName
</cfquery>
<!--- Convert results to array --->
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.StateUSAbb[i]>
<cfset result[i][2]=data.StateName[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
<!--- Get counties by state --->
<cffunction name="getCounties" access="remote" returnType="array">
<cfargument name="stateabb" type="string" required="true">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!--- Get data --->
<cfquery name="data" datasource="bridges">
SELECT '' AS FIPS_COUNTY, ' ALL' as CountyName
FROM lkuCnty
UNION
SELECT FIPS_County, CountyName
FROM lkuCnty
WHERE StateAbb = '#ARGUMENTS.stateabb#'
ORDER BY CountyName
</cfquery>
<!--- Convert results to array --->
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.FIPS_County[i]>
<cfset result[i][2]=data.CountyName[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
</cfcomponent>
If the data is a fixed length you can use NumberFormat to force leading zero's. In general, CF is typeless so there must be some underlying conversion happening that is causing the data to get corrupt. You might try forcing the value toString(), or to debug add something like a single quote as the first character in the column value (eg. SELECT '''' + FIPS_County, '''' + CountyName FROM lkuCnty) to see if they keep all their characters.
[Update]
Based on your comments about how SQL is not returning 5 char, use this updated query to go from INT to VARCHAR with leading zeros.
SELECT DISTINCT
RIGHT('00000' + CONVERT(VARCHAR(5),StateUSAbb),5),
lkuState.StateName
FROM lkuState INNER JOIN tblLoc ON lkuState.FIPS_State = tblLoc.FIPS_State
WHERE (lkuState.StateName <> 'New Brunswick')
UNION
SELECT '' AS StateUSAbb,
' ALL' AS StateName
FROM lkuState
ORDER BY StateName
append a space to the end of the number, then CF will treat it as a string and no leading 0 will be chopped.
simple workaround: <cfset result[i][1]=data.StateUSAbb[i] & " ">
btw, you know that query object is supported for populating cfselect right? So you don't even need the loop. You can do the same workaround but in SQL inside your cfquery
UPDATE: anyway, the idea is that if u want to preserve the leading 0 and keep using CF's built in serializeJSON() or calling the cfc remote method in JSON style (which will internally invoke serializeJSON(), you can append a space so CF will treat it as a string and leading 0 will be preserved. If your script somehow must need "012345" with no trailing space, then look for another JSON seralizer from riaforge or cflib.
You're sure the data returned from your query is a text string which contains the leading zero, rather than just the integer value? Regardless, I think Zachary's suggestion of NumberFormat(x, "00000") is the way to go.