Link to home
Start Free TrialLog in
Avatar of Zac123
Zac123Flag for United Kingdom of Great Britain and Northern Ireland

asked on

help with CFQuery - Joining tables - display current status

hi all,

simple access db with two tables, one contains the original log entry the other table gets updated as to the status of the log entry, simple.

the first query simply outputs all original log  entries:

<cfquery name="display_log" datasource="allied_control_db1">
SELECT *
FROM ops_log_entry
ORDER BY ID DESC
</cfquery>

when inserting new entires into the second table i also pass the ID of the original log entry as well so that i can match up which new entries are related to which original entires - still with me?

this next query is supposed to join the two tables, match up the ID's and take the info from the "current_status" column in second table WHERE MAX DATE/TIME.
the reason for the WHERE is that there may have been loads of entries all linked to the same ID but its the latest one that will hold the most up to date "current_status" - still with me now?

<cfquery name="display_log1" datasource="allied_control_db1">
SELECT current_status
FROM ops_log_entry AS L INNER JOIN new_log_entries AS N
ON ( L.ID = N.id_original_entry )
WHERE N.new_entry_datetime = (SELECT MAX(N1.new_entry_datetime)
FROM new_log_entries AS N1
WHERE N1.id_original_entry = N.id_original_entry)
</cfquery>

the "current_status" should then be displayed in the same table that displays data from the first table (the original entry)

the end result is that you can view a list of all original entires but with their current status.

i'm pretty sure its the MAX DATE TIME thing thats not working it just seems to take any "current_status" and displays the same status for all entries.

could somone please have a look at my code and give me any suggestions, thanks. sorry about any typos, imy very tired and off to bed now :-(
Avatar of Badotz
Badotz
Flag of United States of America image

If the ID numbers grow as the rows are inserted into the table, perhaps MAX(ID) would be a better choice?
Avatar of Zac123

ASKER

yes i cant be sure to get the right result as ther will multipul entries by different users. i think max id might give me the wrong results
Avatar of _agx_
I think you'll need a combination of max datetime and id, in case two records have the same datetime stamp.  Assuming your second table has a unique id, try something like this.  Just change "TheUniqueID" to the name of your ID column.


SELECT  L.ID, N.current_status
FROM  (  ops_log_entry AS L INNER JOIN new_log_entries AS N 
         ON L.ID = N.id_original_entry 
      )
      INNER JOIN 
      (
	   SELECT  N1.id_original_entry, MAX(N1.TheUniqueID) AS MaxNewLogID
	   FROM    new_log_entries AS N1  INNER JOIN 
              (    SELECT   id_original_entry, MAX(new_entry_datetime) AS MaxDateTime
                   FROM     new_log_entries 
                   GROUP BY id_original_entry
              ) 
              AS D ON (N1.id_original_entry = D.id_original_entry 
                   AND N1.new_entry_datetime =  MaxDateTime)
	   GROUP BY N1.id_original_entry
      ) 
      AS MX ON N.TheUniqueID = MX.MaxNewLogID

Open in new window

Avatar of Zac123

ASKER

qucik question, should "TheUniqueID" in your sql above be the ID of the first table that holds the original entry or the ID of the second table that holds the current status?

i dont seem to be able to get it to work. its taking a status from  the second table but its just displaying the same status for row of data, but of course each row will have its own status, they wont all be the same.
"TheUniqueID" should be the ID of the second table:  new_log_entries

Avatar of Zac123

ASKER

ok tried that didnt work.

in the second table there are two ID columns one called new_entry_id (this is the auto id) the other one is called id_original_entry (this is the one that matches the auto ID of the first table)

i cant get it to work with either of these, it just displays the same status for all records. and whats even more confusing is that the status that being displayed isnt even the MAX ID or MAX DateTime - so whats that all about?

i havent made anymistakes here have i?

SELECT  L.ID, N.current_status
FROM  (  ops_log_entry AS L INNER JOIN new_log_entries AS N
         ON L.ID = N.id_original_entry
      )
      INNER JOIN
      (
         SELECT  N1.id_original_entry, MAX(N1.new_entry_id) AS MaxNewLogID
         FROM    new_log_entries AS N1  INNER JOIN
              (    SELECT   id_original_entry, MAX(new_entry_datetime) AS MaxDateTime
                   FROM     new_log_entries
                   GROUP BY id_original_entry
              )
              AS D ON (N1.id_original_entry = D.id_original_entry
                   AND N1.new_entry_datetime =  MaxDateTime)
         GROUP BY N1.id_original_entry
      )
      AS MX ON N.new_entry_id = MX.MaxNewLogID
No it looks correct.   Let's say this is the sample data in the two tables

ops_log_entry
id      Title
1      item 1
2      item 2
3      item 3

new_log_entries
new_enew_entry_id      id_original_entry      current_status      new_entry_datetime
1      1      started      12/4/2007 11:34:01 AM
2      1      work a      12/6/2007 7:34:01 AM
3      1      work b      12/6/2007 7:34:01 AM
4      3      finished      12/6/2007 9:34:21 AM
5      2      opened      12/5/2007 2:34:27 PM
6      2      closed      12/6/2007 10:34:31 AM

The query would return

ID      current_status
1      work b
2      closed
3      finished

It returns the status "work b" for ID #1 because its the record in the second table with the maximum datetime and ID number.  Are these the results you're looking for?
Avatar of Zac123

ASKER

yes i have read what you havewritten carefully and you are correct. the only difference is the last bit, the query is not pulling "work b" for ID #1

take a look, ive uploaded a working version here:

http://www.alliedcontrol.net/index.cfm?log

add a new entry then click on the +plus sign to add a new status, add a few you'll see how is works. i have made the column red that i am having trouble with.
Yes, but the query posted would produce "work b" for #1.  So unless I've misunderstood something,  that suggests your query code is different or perhaps your cfoutput code is wrong.    

If you dump the query before doing your cfoutput.  Are all the statuses "Re-opened" or are they different?
<cfdump var="#yourQuery#">

Avatar of Zac123

ASKER

ok this is the result of the cf dump (which i have never done before, very handy thanks)

 CURRENT_STATUS ID
1 Re-opened  16  
2 Waiting on client  18  
3 Closed  19  
4 Remains open  21  
5 Waiting on guard  22  
6 Waiting on guard  23  
7 Closed  25  

so what does this tell us? is the output incorrect?
Avatar of Zac123

ASKER

by the way to output the "current_status" i'm using: {display_log1.current_status}
> is the output incorrect?

Yes.   If the query results are correct, and you're using that query to produce the output, then .. yes, the problem must be in your output code.
> by the way to output the "current_status" i'm using: {display_log1.current_status}

I think that's your problem.  Unless you're looping through the "display_log1" query,  

      #display_log1.current_status#  

only outputs the status in the first record.  Make sense?
Avatar of Zac123

ASKER

ahhhh right, now we're getting somewhere.

so this {display_log1.current_status} is no good. i need loop through the display_log1 query?

to do this i just put cfloop infront of the query dont i? like....

<cfloop query name"display_log ...................

would that work?
It should, but it depends on your output code.  Also, if you're using nested query loops you may need to specify the row indexes.  But try it first.   You could also try joining display_log1 with your other query.  Either in a db query or using a QoQ

<cfloop ...>
   <cfloop ...>
   </cfloop>
</cfloop>

Avatar of Zac123

ASKER

ok so i wrapped the output in a cfloop like so:

<cfloop query="display_log1>#display_log1.current_status#</cfloop>

what this has done is place all of the results in every row. so do i now need to add a condition to the loop? or something?
Avatar of Zac123

ASKER

you could see whats happening here:

http://www.alliedcontrol.net/index.cfm?log
Oh, I see what you're saying.  You have to either JOIN display_log1 to the other query you're using in the output ... or do some kind of conditional loop

<cfloop query="display_log1>
     <cfif display_log1.The_original_ID EQ  theOuterQuery.The_Original_ID>
          then display current_status
     </cfif>
</cfloop>

But again, you may have to use a row index if you're using nested loops.   I can't say more without seeing the output code.

Avatar of Zac123

ASKER

nearly there...

not sure i know how to join the two queries properly so i first off tried the cfif route. tried lots of different combinations of the cfif:

<cfloop query="display_log1">
<cfif display_log1.ID_original_entry EQ display_log1.id_original_entry>#display_log1.current_status#</cfif>
</cfloop>

also not sure about the row indexing you mentioned. played around with startrow"?" endrow"?" but that didnt work, off to bed now, look at it in the morning with fresh eyes! :-)
Could you post the output code tomorrow?  That might help us "cut to the chase" so to speak ;-)

Avatar of Zac123

ASKER

Good morning,

i thought the best thing would be to post the entire page. i appreciate your help with this.


 
<cfquery name="display_log" datasource="allied_control_db1" >
SELECT *
FROM ops_log_entry
ORDER BY ID DESC 
</cfquery>
 
 
<cfquery name="display_log1" datasource="allied_control_db1">
SELECT  L.ID, N.*
FROM  (  ops_log_entry AS L INNER JOIN new_log_entries AS N 
         ON L.ID = N.id_original_entry 
      )
      INNER JOIN 
      (
	   SELECT  N1.id_original_entry, MAX(N1.new_entry_id) AS MaxNewLogID
	   FROM    new_log_entries AS N1  INNER JOIN 
              (    SELECT   id_original_entry, MAX(new_entry_datetime) AS MaxDateTime
                   FROM     new_log_entries 
                   GROUP BY id_original_entry
              ) 
              AS D ON (N1.id_original_entry = D.id_original_entry 
                   AND N1.new_entry_datetime =  MaxDateTime)
	   GROUP BY N1.id_original_entry
      ) 
      AS MX ON N.new_entry_id = MX.MaxNewLogID
</cfquery>
 
 
 
<cfform action="ops/insert_log_entry.cfm" method="post" name="ops_log_form">
<table width="0%" border="0" cellspacing="0" cellpadding="2">
<tr>
 
<td rowspan="2" align="left" valign="top">
<label for="site_id_no">Site/ID</label>
<cfinput type="text" name="site_id_no" id="site_id_no" tabindex="1">
 
<label for="ops_type">Type</label>
<cfselect
tabindex="3" 
name="ops_type"
id="ops_type"
required = "Yes"  
message = "message text"   
onError = "error text" >
<option selected="selected" value="not selected">not selected</option>
<option value="Phoned in">Phoned in</option>
<option value="Phoned out">Phoned out</option>
<option value="Task">Task</option>
<option value="Log entry">Log entry</option>
</cfselect>
</td>
 
<td rowspan="2" align="left" valign="top">
<label for="site_id_name">Site or emp name</label>
<cfinput type="text" name="site_id_name" id="site_id_name" tabindex="2">
 
<label for="ops_priority">Priority</label>
<cfselect 
tabindex="4"
name="ops_priority"
required = "Yes"  
message = "message text"   
onError = "error text" >
<option selected="selected" value="not selected">not selected</option>
<option value="HIGH">HIGH</option>
<option value="Medium">Medium</option>
<option value="low">low</option>
</cfselect>
</td>
 
<td rowspan="2">
<label for="log_entry">Log entry or task</label>
<cftextarea name="log_entry" id="log_entry"  tabindex="5" wrap="virtual"></cftextarea>
</td>
 
<td align="left" valign="top">
<cfinput type="hidden" name="log_entry_date_time" value="NOW())">
<cfinput type="hidden" name="ops_status" value="open">
</td>
 
 
<td align="left" valign="top">
<cfinput name="Submit" type="submit" id="submit_button" value="S" alt="Save">
</td>
    
</table>
 
 
 
 
 
 
 
 
 
 
 
 
 
<table width="800" border="1" align="left" cellpadding="2" cellspacing="0">
  <tr>
    <td>Site/ID No.</td>
    <td>Type</td>
    <td>Name</td>
    <td>Priority</td>
    <td>Log/task</td>
    <td>Entry/task created</td>
    <td bgcolor="#FF0000">Status (each entry should have its own status)</td>
    <td>Options</td>
  </tr>
  <cfoutput query="display_log">
    <tr>
      <td>#display_log.site_id_no#</td>
      <td>#display_log.ops_type#</td>
      <td>#display_log.site_id_name#</td>
      <td>#display_log.ops_priority#</td>
      <td>#display_log.log_entry#</td>
      <td>#DateFormat(display_log.log_entry_date_time)# @ #TimeFormat(display_log.log_entry_date_time)#</td>
      <td bgcolor="##FF0000">
      
<cfloop query="display_log1">
<cfif display_log1.ID_original_entry EQ display_log1.id_original_entry>#display_log1.current_status#</cfif>
</cfloop>
</td>
      <td><a href="../ops/edit_log.cfm?id_log=#display_log.ID#"><img src="../images/gifs/plus.gif" alt="Edit/Add" width="15" height="15" border="0" /></a></td>
    </tr>
  </cfoutput>
</table>
</cfform>
 
<cfdump var="#display_log1#">

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of _agx_
_agx_
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Zac123

ASKER

woooo hooooo its workin! thanks so much for your time and paitence. ive learnt alot. i'm going to read up on joining queries, i think this is something i'll be using a lot of with this site.

thanks again.
Avatar of Zac123

ASKER

thanks agx, you have been extreemly helpful. no doubt i'll be posting for help again in the future. thanks.
You're welcome!  Yes, read all you can about JOINs.  They're very powerful and you'll almost certainly need them in most applications.  Happy reading :-)