Take the following query example:
<cfquery name="Test" Datasource = "TestDB">
Select * from Table_Test
</cfquery>
Assume that the "Test" query returns 10 rows. I want to show single row on current time.
Note: I do not want to change the SQL statement.
If you know your row number, Test.columnName[RowNumber] will show you the value of the columnName in specified row number.
If you want one random row from the query:
<cfset start = randRange(1, Test.recordCount)>
<cfoutput>
#Test.name[start]# #Test.email[start]#<br>
</cfoutput>
No need to loop.
NOTE: It is more efficient to modify the query to get a random row.
How to request a random row in SQL?
Related
I have a query object which contains 5 columns, but I only need to add 4 columns to the spreadsheet. When I am using <cfset spreadSheetAddRows(spreadSheetObj,qryObj)> it is adding all the columns to the spreadsheet. I cannot remove the 5th column from the query as it is required for some other purpose.
So How can I add only 4 columns from the query to spreadsheet?
Ex: My query contains 4 columns like "Id,Name,Roll,CGPA"
But my Excel sheet should contain only "Id,Name,Roll".
How to do this?
You could do a Query-of-Query to create a temporary query that you can then use to pump into your spreadSheetAddRows().
<cfquery name="local.spreadsheetQuery" dbtype="query">
SELECT Id,Name,Roll
FROM variables.originalQuery
</cfquery>
Then use <cfset spreadSheetAddRows(spreadSheetObj,local.spreadsheetQuery)> instead of <cfset spreadSheetAddRows(spreadSheetObj,variables.originalQuery)>.
Just add each row individually with SpreadsheetAddRow(spreadsheetObj, data [,row, column, insert]);
And for columns use SpreadsheetAddColumn(SpreadsheetObj, data[, startRow, startColumn, insert]);
SpreadsheetAddRow Documentation
SpreadsheetAddColumn Documentation
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.
I'm doing the following query of queries. The first dump of the query shows the entire excel sheet, the second dump shows the results of the second query.
I'm doing a validation check of the excel sheet to make sure there are no more pit bulls breeds brought into the system and I need to be able to tell the user which row on the excel sheet has the pit-bull.
How do I get the row numbers from the first row to appear in the second row? So the user can make changes on the excel sheet.
Do I have to resort to editing the excel document when it was first uploaded into the server and add a row number column to it? There is probably a better way to accomplish this.
<cffunction name="validateExcelSheet" access="public" output="yes" returnType="void"
hint="check dogs">
<cfspreadsheet
action="read"
src="#SESSION.theFile#"
headerrow= "1"
excludeHeaderRow = "true"
query = "allData"
rows = "1-#lastRow#" />
<cfscript>
pitBullcheck = new Query(
sql ="SELECT * FROM allData where breed like 'Pit%' ",
dbtype = "query",
allData = allData);
pitBullresult = pitBullcheck.execute().getResult();
</cfscript>
</cffunction>
Here's a tag based version of cfquery
<cfquery name="pitBullresult" dbtype="query">
SELECT *
FROM allData
WHERE breed LIKE 'Pit'
</cfquery>
That is not something you can do with cfspreadsheet. CFSpreadsheet only returns the cell values. It does not provide the physical row numbers, within the spreadsheet, that contained those values.
Also, something else to keep in mind is that CFSpreadsheet only returns "logical" (ie populated) rows/cells. That is not the same as the "physical" row numbers 1,2,3,... and column headers A,B.C.... that you see in Excel. Since users can enter values anywhere within a spreadsheet, logical and physical are not always the same thing.
For example, create a blank spreadsheet. Then enter values in cells
A2 and A25. Now run your code above. While you might expect the
resulting query to contain twenty-five (25) records, it will only
contain two (2), because only two cells were populated.
query
Row | COL_1
1 | Value in cell A2 (physical row 2)
2 | Value in cell 25 (physical row 25)
I think best you could do with cfspreadsheet is to loop through the query and display the relative row number within the results ie query.currentRow. If the populated data always starts within the first few rows, that might be good enough for your purposes. If not, it could get a bit confusing ...
That said, technically you could get the real physical row numbers. However, it requires much lower level code, which quite honestly ... seems like a lot of work, for very little gain.
In my code, I first create the Query Object:
<cfset memberData = QueryNew('slug,pos,firstname,lastname,email') />
<cfset temp = QueryAddRow(memberData, #numMembers#) />
<!--- LOOP POPULATES QUERY OBJECT --->
<cfloop...</cfloop>
I can then verify that it has been populated by running the following (which outputs as expected):
<cfoutput query="memberData">
#slug# - #pos#<br>
</cfoutput>
I then try to query the memberData Query Object and all hell breaks loose. If I run:
<cfquery name="members" dbtype="query">
SELECT slug,pos,firstname,lastname
FROM memberData
WHERE slug = #slug#
</cfquery>
I get this error:
Query Of Queries runtime error.
The select column reference [university] is not a column in any of the tables of the FROM table list.
In the output test mentioned above, I can verify that "university" is one of the values in the slug column. Clearly I'm missing something in my approach, but I'm baffled as to what it might be. Any help would be greatly appreciated!
Query Of Queries runtime error.
The select column reference
[university] is not a column in any of the tables of the FROM table
list
Your error was caused by absence of quotes in where clause and nothing else:
This expression find rows where the value in slug column equals the value in CF slug variable (String):
WHERE slug = '#slug#'
On the other hand this expression means find rows where value in the slug column equals the value contained in the column named in the CF slug variable (String):
WHERE slug = #slug#
The most likely cause of why you needed to change to SELECT * is CF query caching. So changing it back now should solve the problem. And always use <cfqueryparam .../> as suggested by "Al Everett"
Well, it's not quite answering the question asked, but it's close enough for what I needed:
<cfquery name="members" dbtype="query">
SELECT *
FROM memberData
WHERE slug = '#slug#'
</cfquery>
I had tried the wrapping #slug# in single quotes prior to posting with no success, but doing that plus changing the query to SELECT * fixed the issue. For my content, * only adds one more value retrieved, so not really a problem in slowing down the process.
I am outputting a query but need to specify the first row of the result. I am adding the row with QueryAddRow() and setting the values with QuerySetCell().
I can create the row fine, I can add the content to that row fine. If I leave the argument for the row number off of QuerySetCell() then it all works great as the last result of the query when output. However, I need it to be first row of the query but when I try to set the row attribute with the QuerySetCell it just overwrites the first returned row from my query (i.e. my QueryAddRow() replaces the first record from my query). What I currently have is setting a variable from recordCount and arranging the output but there has to be a really simple way to do this that I am just not getting.
This code sets the row value to 1 but overwrites the first returned row from the query.
<cfquery name="qxLookup" datasource="#application.datasource#">
SELECT xID, xName, execution
FROM table
</cfquery>
<cfset QueryAddRow(qxLookup)/>
<cfset QuerySetCell(qxLookup, "xID","0",1)/>
<cfset QuerySetCell(qxLookup, "xName","Delete",1)/>
<cfset QuerySetCell(qxLookup, "execution", "Select this to delete",1)/>
<cfoutput query="qxLookup">
<tr>
<td>
#qxLookup.xName#
</td>
<td>#qxLookup.execution#</td>
</tr>
</cfoutput>
Thanks for any help.
I would add some kind of sort order column to your original query, populating it with a fixed value of 1.
<cfquery name="qxLookup" datasource="#application.datasource#">
SELECT xID, xName, execution, 1 as sortorder
FROM table
</cfquery>
Set the value of that column in your synthetic row to a value of 0.
<cfset QueryAddRow(qxLookup)>
...
<cfset QuerySetCell(qxLookup, "sortorder", "0",1)>
Then use query-of-queries to reorder the recordset by the sortorder column.
<cfquery name="qxLookup" dbtype="query">
select xid, xname, execution
from qxLookup
order by sortorder
</cfquery>
Well I have dealt with this problem before, for me the answer was to have 2 seperate queries.
1st, being your normal query, 2nd being the query of queries, then do a union of them, with the qofq being above the normal query, and that should give you results in the order you want.
Something like this:
<cfquery name="table_a_results" datasource="">
select a, b, c
from table_a
</cfquery>
cfset table_b = querynew("a, b, c")
cfset temp = queryaddrow("table_b")
cfset temp = querysetcell(table_b,10)
cfset temp = querysetcell(table_b,20)
cfset temp = querysetcell(table_b,30)
<cfquery name="final_query" dbtype="query">
select a, b, c
from table_b
union
select a, b, c
from table_a_results
</cfquery>
Then using this tool you can put queries in any order you like, but remember to use the order by tag, to change order...
Just an alternative to above, but you could take ColdFusion out of the picture and do this solely in the SQL using something like (eg in oracle)
select 'myinsertedvalue' from dual
union
select myrealvalues from mutable
You could combine with Kens sort column to get full ordering. Assuming you are getting the main query from a DB!