My understanding is that nulls last is not possible with QoQ. How do I trick coldfusion into sorting null values last whether i'm sorting the row ascending or descending?
I've tried using case in the SELECT and ORDER part of query, but looks like CF is not liking it (running on railo)
There may be better options, but one simple trick is to add a column representing sort priority. Assign records with non-null values a higher priority than null values. Then simply sort by the priority value first, then any other columns you want. Since the null values have a lower priority number, they will always sort last.
<!--- 1 - non-null values 2 - null values --->
SELECT 1 AS SortOrder, SomeColumn
FROM theQuery
WHERE SomeColumn IS NOT NULL
UNION ALL
SELECT 2 AS SortOrder, SomeColumn
FROM theQuery
WHERE SomeColumn IS NULL
ORDER BY SortOrder, SomeColumn ASC
(It is worth noting you could probably do something similar in your database query using order by instead of union.)
QoQ on both ColdFusion and Railo have a very limited SQL vocab, and there's nothing that deals with how to collate nulls. So as #Leigh has suggested, add another column - without any nulls - which represent the sorting you want.
Or, better, if possible deal with all this in the DB. Obviously this is not always possible (as the record set you're querying might not have come from a DB in the first place ;-)
...there was one more way, but it relies on values being NULL and not empty ''.
I'm going from memory here, but this is essentially it, using || only works if the value is non-null, so using the null values descending sort first, I get the values at the end.
<cfquery>
SELECT *, '1' || #sortCol# as isNull
FROM table
ORDER BY isNull desc, #sortCol#
</cfquery>
Note I'm not actually advocating the use of this and I'm not sure if CF would handle it the same way
Related
To simplify my question, consider the following table in dolphindb:
t=table(1..5 as id, 1 NULL 3 NULL NULL as x)
I would like to forward fill nulls ONLY for the rows that I specify. For example, only for the row with id=2. I tried the following SQL query but the result was unexpected.
update t set x=ffill(x) where id=2
The table t was not updated at all. I would appreciate it if someone can point out the mistake in my code. Thanks!
The 'where' condition in SQL is always executed before the 'select' calculations. Therefore in this case you lose the information about id=1. Try this:
update t set x=iif(id==2, ffill(x), x)
This uses dolphindb function iif. Effectively it is a loop.
Is there an API call provided by mysql++ to get the number of rows returned by the result?
I have code structured as follows:
// ...
Query q = conn.query(queryString);
if(mysqlpp::UseQueryResult res = query.use()){
// some code
while(mysqlpp::Row row = res.fetch_row()){
}
}
My previous question here will be solved easily if a function that returns the number of rows of the result. I can use it to allocate memory of that size and fill in as I iterate row by row.
In case anyone runs into this:
I quote the user manual:
The most direct way to retrieve a result set is to use Query::store(). This returns a StoreQueryResult object,
which derives from std::vector, making it a random-access container of Rows. In turn,
each Row object is like a std::vector of String objects, one for each field in the result set. Therefore, you can
treat StoreQueryResult as a two-dimensional array: you can get the 5th field on the 2nd row by simply saying
result[1][4]. You can also access row elements by field name, like this: result[2]["price"].
AND
A less direct way of working with query results is to use Query::use(), which returns a UseQueryResult object.
This class acts like an STL input iterator rather than a std::vector: you walk through your result set processing
one row at a time, always going forward. You can’t seek around in the result set, and you can’t know how many
results are in the set until you find the end. In payment for that inconvenience, you get better memory efficiency,
because the entire result set doesn’t need to be stored in RAM. This is very useful when you need large result sets.
A suggestion found here: http://lists.mysql.com/plusplus/9047
is to use the COUNT(*) query and fetch that result and then use Query.use again. To avoid inconsistent count, one can wrap the two queries in one transaction as follows:
START TRANSACTION;
BEGIN;
SELECT COUNT(*) FROM myTable;
SELECT * FROM myTable;
COMMIT;
I've got a series of queries that I do to get 5 results at random, the problem is that it is taking a while to get through them, mostly because it involves a loop to assign a rand value that I can order by (which Railo can do in-query)
I was wondering if anyone has dealt with this and knows of a way of speeding it up.
I'm below 200ms, which isn't bad but I'm sure it can be sped up.
You probably don't need to use QoQ at all.
One option might be to write your original query as:
SELECT TOP 5 whatever,you,need
FROM table
ORDER BY rand()
Update the syntax depending on which database server you're using.
Another option, which could be done for both regular queries and QoQ, would be:
select only the primary keys
shuffle the array (i.e. createObject("java","java.util.Collections").shuffle(Array))
use the first five items in the array to select the fields you need.
No looping or updating, just two simple selects.
Of course if your primary key is just an auto-incrementing integer, you might get away with SELECT MAX(Id) then use RandRange to pick your five items.
For Microsoft SQL Server (v2005+) this query syntax will get 5 random records:
SELECT TOP 5 *
FROM table
ORDER BY NEWID()
I'm on Railo (ColdFusion 9) and neither TOP nor NEWID() works in a Query of Query (QoQ). If you happen to fall into this use case, and you must act upon a QoQ, then here's a solution:
<cfquery name="randomizedQueryObject" dbtype="query" maxrows="10">
SELECT *, RAND() as rand
FROM someQueryObject
ORDER BY rand
</cfquery>
This returns 10 random items from a larger result set and works in a QoQ. Short and simple.
Say I have a query like the one below. What would be the best way to put each value into an array if I don't know how many results there will be? Normally I would do this with a loop, but I have no idea how many results there are. Would I need run another query to count the results first?
<CFQUERY name="alllocations" DATASOURCE="#DS#">
SELECT locationID
FROM tblProjectLocations
WHERE projectID = '#ProjectName#'
</CFQUERY>
Depending on what you want to do with the array, you can just refer to the column directly for most array operations, eg:
i = arrayLen(alllocations["locationID"]);
Using that notation will work for most array operations.
Note that this doesn't "create an array", it's simply a matter that a query columns - a coldfusion.sql.QueryColumn object is close enough to a CFML array for CF to be able to convert it to one when an array is needed. Hence the column can be passed to an array function.
What one cannot do is this:
myArray = q["locationID"];
This is because by default CF will treat q["locationID"] as a string if it can, and the string value is what's in the first row of the locationID column in the q query. It's only when an array is actually required will CF convert it to an array instead. This is basically how loose-typing works.
So if you just need to pass your query column to some function that expects an array, you can use the syntax above. If you want to actually put the column into a variable, then you will need to do something like this:
myArray = listToArray(valueList(q.localtionID));
NB: make sure you use <cfqueryparam> on your filter values instead of hard-coding them into your SQL statement.
myquery.column.toArray() is also a good undocumented choice.
Since you're only retrieving 1 field value from the query, you could use ValueList() to convert the query results into a comma-delimited list of locationIds, then use listToArray() to change that list into an array.
If you were retrieving multiple field values from the query, then you'd want to loop through the query, copy all the field values from the given row into a struct, and then add that struct to an array using arrayAppend().
(If you're not familiar with these functions, you can look them up in the Adobe docs or on cfquickdocs.com).
PostgreSQL by default considers NULL values as the highest, and thus sorts them first for descending queries and last for ascending ones.
You can modify this behaviour per query or at index creation by specifying 'NULLS LAST' or 'NULLS FIRST'.
How can I use this in conjunction with the Django ORM, without needing to use raw queries?
I.e. when I add to my query_set something like qs.order_by("-publish_start"), how can I specify sorting for nulls? Or, as an alternative, upon field/index declaration.
I figured out a way that accommodates DB engines that work either way (null as highest or lowest value) by using extra, making the null check a boolean, and when sorting booleans false < true seems to be universal:
qs = qs.extra(select={'null_start': "publish_start is null"},
order_by=['null_start', '-publish_start'])