You are missing some Flash content that should appear here! Perhaps your browser cannot display it, or maybe it did not initialize correctly.

Utilizing views as a theme layer to a custom query

 
 

We had a client requirement that a single view be the combination of:

  1. a random list of attorneys with offices in a given state
  2. a random list of attorneys that are licensed in a given state.

There should be no duplications and all of list 1 must precede list 2. We could not accomplish this with views alone. After talking to Earl, we were able to access the created SQL statement within views. Here we built each of the two queries. Then, we defined a 'pre' exit and replaced the query in our view with a new one.

The new query is in the form of:

SELECT node.nid FROM ( ( select #1 ) UNION (select #2 ) ORDER BY .... ) AS node.

This is especially important in that we absolutely have to name our selected fields the same as what views would typically name them. If you don't preserve the same naming structure it will simply not work. Now this is only true for the selected fields. Fields on which you join, filter, etc can utilize any naming convention you desire. Of course, both of the select statements were required to provide the exact same column output.

So, as an example the statement looked something like: (with LEFT JOIN detail left out for easier reading)

SELECT node.nid
FROM (
  ( // First select statement
    SELECT node.nid, RAND() as _order
    FROM node node
    WHERE node.attorney_state='%s'
  )
  UNION // concatenate to next
  SELECT
  ( // Second select statement
    SELECT node.nid, (1+RAND()) as _order
    FROM node node
    WHERE node.licenses_state = '%s'
  )
  // This does the sort on all the selects together.
  ORDER BY _order
)
// Now, for Drupal, this outer select MUST be aliased as 'node'.
AS node;

Making it work:

Some of the secret sauce was:

  • use of an outer select with an internal union
  • The outer select needed to be aliased to node for it to work.
  • we only needed the nid as all the data was pulled using node-> syntax.
  • There seemed to be bug in cck based on this, obviously, edge case and it took 2 lines of code to fix.
    • cck expects 'vid' to absolutely have a value.
    • wrapping an if ($vid)... around that expectation removed the warning error that we were getting.
    • bottom line... we hacked it, but hopefully it will make sense to the cck authors and it can be submitted back to the module.
  • the views hook was hook_views_pre_execute(&$view) and we altered the query directly via $view->build_info['query']. If you'd like to preserve the dynamic nature of certain aspects of the views interface, you must respect your $view->build_info['query_args']. This may require some alteration as well.
  • Note that we did a RAND() and 1+RAND(). This is because RAND() returns a random decimal between 0 and 1, thus 1+RAND() would be a random decimal between 1 and 2, allowing us to order by this random number and be sure that our second query's results ALWAYS come after the first query.
 
The content of this field is kept private and will not be shown publicly.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • HTML tags will be transformed to conform to HTML standards.

More information about formatting options

 
© 2009 the Worx Company
site designed by the Worx Company · site hosted by Hosts of America