I have an events page where I need to display the events for each day. I've gotten it to this point, so I'm making progress.
The database has 3 tables: fairdays, eventtypes, events
fairdays: id, fairdaydate (datetime), daycolor, description
eventtypes: id, eventtype <-- This table is for the input select in the "add event form"
events: id, eventname, eventtype, eventday (datetime), eventtime (datetime)
My intent is to display the day with the description, then under that is the event types, then under each of those is the corresponding events.
I haven't worked out how to display the event type sub heading, then the individual events under each of those, but here's my code so far. Any help would be hugely appreciated.
<cfquery datasource="fairscheduledb" name="getfairdays">
select * from fairdays
</cfquery>
<cfquery datasource="fairscheduledb" name="getfairevents">
select * from events ev
inner join fairdays fd on fd.fairdaydate = ev.eventday
where ev.eventday = fd.fairdaydate
</cfquery>
<cfloop query="getfairdays">
<cfoutput>
<div class="schedulebox">
<div class="schedulehead" style="color: ###getfairdays.daycolor#;">#dateformat(getfairdays.fairdaydate,"dddd, mmmm dd")#</div>
<div class="schedulesubhead" style="color: ##ffffff; background: ###getfairdays.daycolor#;">#getfairdays.description#</div>
<cfoutput query="getfairevents">
<div class="scheduleitem" style="float: left; width: 75px; text-align: right;">#LCase(TimeFormat(getfairevents.eventtime,"h:mmtt"))#</div>
<div class="scheduleitem" style="float: left; width: 550px;">#getfairevents.eventname#</div><br/>
</cfoutput>
</div>
</cfoutput>
</cfloop>
Here's what the list of days and events should look like:
<div class="schedulebox">
<div class="schedulehead" style="color: #4CC417;">Friday, February 22</div>
<div class="schedulesubhead" style="color: #ffffff; background: #4CC417;">Opening Ceremony 4:30pm at Gate<br/>5:00 - 6:00pm - Free Admission & Free Rides</div>
<div class="scheduleitemtitle" style="color: #4CC417;">Strolling Acts</div>
<div class="scheduleitem">5:30pm - Scotts Magic Show</div>
<div class="scheduleitem">6:30pm - Rock-It the Robot</div>
<div class="scheduleitem">7:30pm - Scotts Magic Show</div>
<div class="scheduleitem">8:30pm - Rock-It the Robot</div>
<div class="scheduleitemtitle" style="color: #4CC417;">Acts</div>
<div class="scheduleitem">5:30pm - Sea Lion Show</div>
<div class="scheduleitem">6:00pm - Alligator Wrestling</div>
<div class="scheduleitem">6:30pm - Petting Zoo Presentation </div>
<div class="scheduleitem">8:00pm - Alligator Wrestling</div>
<div class="scheduleitem">8:30pm - Petting Zoo Presentation </div>
<div class="scheduleitem">9:00pm - Sea Lion Show</div>
<div class="scheduleitemtitle" style="color: #4CC417;">Stage Acts</div>
<div class="scheduleitem">7:00pm - Youth Royalty</div>
<div class="scheduleitemtitle" style="color: #4CC417;">Livestock Program</div>
<div class="scheduleitem">6:00pm - Beef Breeding Screening</div>
<div class="scheduleitem">7:00pm - Horse Judging Competition</div>
</div>
First, you don't need the first query.
Next, add
order by eventday
to query getfairevents. That will enable you to do this:
<cfoutput query="getfairevents" group = "eventday">
#eventday#
<cfoutput>
output other stuff here (individual events and times)
</cfoutput>
</cfoutput>
(This is too long for comments ...)
To expand on Dan's answer, he is suggesting a more efficient way of producing that output by using JOIN's and cfoutput's group feature (emphasis is mine):
... Eliminates adjacent duplicate rows when data is sorted. Use if you
retrieved a record set ordered on one or more a query columns. For
example, if a record set is ordered on "Customer_ID" in the cfquery
tag, you can group the output on "Customer_ID."
For your JOIN's you will need to include all three tables to grab all of the columns you need. I cannot test it right now, but something along these lines. (Notice the results are sorted the same way you wish to display them ie by event date, type and time)
SELECT ev.eventDay, t.EventType, ev.EventTime
FROM fairdays fd
INNER JOIN events ev ON ev.eventDay = fd.fairdaydate
INNER JOIN eventType t ON t.ID = ev.EventType
ORDER BY ev.eventDay, t.EventType, e.EventTime
Once you have the sorted results, use "group" generate the desired results. Be sure to group by the same columns, in the same order, as the sql query. Otherwise, it will not work correctly.
<cfoutput query="yourQuery" group="EventDay">
<!--- display event dates --->
#EventDay# <hr/>
<!--- event types for current date --->
<cfoutput group="EventType">
#EventType#<br/>
<!--- individual events --->
<cfoutput>
#EventTime# <br/>
</cfoutput>
</cfoutput>
</cfoutput>
Update from comments:
As discussed in the comments, if you want to retrieve all fairdays (even ones without a matching event) use outer joins instead of inner joins.
SELECT fd.fairDayDate, t.ID, ev.EventType, ev.EventTime
FROM fairdays fd
INNER JOIN events ev ON ev.eventDay = fd.fairDayDate
INNER JOIN eventType t ON t.ID = ev.EventType
ORDER BY fd.fairDayDate, t.ID, e.EventTime
Again, since the cfoutput "group" feature requires sorted query data to work properly, if you change the ORDER BY clause, be sure to update the "group" columns to match your ORDER BY clause. ie Group by fairDayDate first, then event ID:
<cfoutput query="yourQuery" group="fairDayDate">
<!--- display event dates --->
#fairDayDate# <hr/>
<!--- event types for current date --->
<cfoutput group="ID">
#EventType#<br/>
<!--- individual events --->
<cfoutput>
#EventTime# <br/>
</cfoutput>
</cfoutput>
</cfoutput>
Related
When a user clicks edit of a specific row in a table, I want the input textboxes in the same page to be filled with that row's details. I tried this but it did not work.
<cfquery name="getDataForEdit" datasource="dsn">
select * from usercardetails where id = '#url.id#'
</cfquery>
<cfoutput>
<cfset #form.username# = #getDataForEdit.username#>
</cfoutput>
Try this as an example to get you going....
<cfquery name="getDataForEdit" datasource="dsn">
select * from usercardetails where id = '#url.id#'
</cfquery>
<!---
OPTIONAL IMPROVEMENT: You might change your SQL to use CFQueryParam, this will protect against SQL injection
select * from usercardetails where id = <cfqueryparam cfsqltype="CF_SQL_NUMERIC" value="#url.id#" />
--->
<!---
OPTIONAL FOR DEBUGGING: If you uncomment this block it will show you the results of your query.
<cfoutput><cfdump var="#getDataForEdit#" label="getDataForEdit" expand="No" /><br /></cfoutput>
--->
<cfoutput>
<cfif getDataForEdit.recordcount is 1> <!--- Check that you only get one row back in results --->
<!--- Coldfusion will build forms for you using cfform, but many coders keep away from it, so instead you need to build the HTML of your form yourself. --->
<form action="index.cfm" method="post">
<p><label for="username">Username</label><input type="text" id="username" name="username" value="#getDataForEdit.username#" /></p>
<p><input type="submit" id="butty01" name="butty01" value="Go" /></p>
</form>
<cfelseif getDataForEdit.recordcount is 0> <!--- If no results --->
<p>No records found</p>
<cfelse> <!--- Anything else will mean many results --->
<p>An error occurred (Multiple records with this ID found)</p>
</cfif>
</cfoutput>
I've put comments in the code around some optional improvements.
Also note that...
<cfset #form.username# = #getDataForEdit.username#>
will be causing you problems.
<cfset username = getDataForEdit.username>
Will create/set a variable username equal to the value of the username column in your query. The # tags are not necessary in this context. # prints out the value of a variable, so you could have done this...
<cfset username = "#getDataForEdit.username#">
Which would print the value of the username column into a string of text (the only thing in the string being the value), and the string of text would have been assigned to the variable username.
form
is a reserved word, as it is a structure (it's worth looking up structures) that contains all of the form variable data posted to your page. You can inspect form by using cfdump
<cfoutput><cfdump var="#form#" label="form" expand="No" /><br /></cfoutput>
To print out one of the values inside form you can do
#form.username#
So (and very confusingly when you're a beginner)...
<cfset #form.username# = #getDataForEdit.username#>
Will create a variable with the name that corresponds to the value of the form field username posted to your page, and fill it with the username from your query. You really don't want that.
Keep at it. Once you get a few basic concepts sorted Coldfusion is a lovely language to code in.
From the menu I have
<cfset temp =valuelist(GetDeptNum.csedept_name)>
<cfset ChangedElement = ListGetAt(temp, 2)>
<cfset TempToo = ListSetAt(temp, 2, ",")>
<cfdump var=#TempToo#>
<li class="fullChild"><a id="corporate" href="phonelistsearch_test.cfm?corporate" onclick="changeClass('corporate')" >Corporate</a><a class="opener"></a>
<ul>
<cfloop From = "1" To = "#ListLen(temptoo)#" INDEX = "Counter">
<cfoutput><li> #ListGetAt(temptoo, Counter)#
</cfoutput>
</cfloop>
</ul>
</li>
I have a table which I use a filter to search the table, working, see http://jsfiddle.net/45grrk3m/ .
How would I link it to a table so when I click on the plus sign I can choose different choices
and it will only filter those rows in that csedept_name I click?
Both tables GetUsers and GetDeptNum share the csedept_id collumn.
So from the menu dropdown I get the name right now which works GetDeptNum.csedept_name,
but not sure how I can make the connection between the menu and table.
You need to think about how you're generating the table.
Each option in your table should be a hyperlink back to the page (or ajax....) which passes the option selected. Your SQL query would then refine the search, and the table is recreated using the refined resulty
I have a page that shows a schedule of events over a period of time. Thanks to Leigh on this site, I was able to get it working the way I wanted, except for one small issue. One of the events is placed at the bottom of one of the lists that is sorted by the datetime column "eventtime". I'm baffled.
Here's my code:
<cfquery datasource="fairscheduledb" name="getfairevents">
SELECT fd.FairDayDate, fd.daycolor, fd.description, ev.eventname, ev.eventday, t.eventtype, ev.eventtime
FROM fairdays fd
LEFT OUTER JOIN events ev ON ev.eventday = fd.fairdaydate
LEFT OUTER JOIN eventtypes t ON t.eventtype = ev.eventtype
ORDER BY fd.fairDaydate, t.id, ev.eventtime
</cfquery>
<cfoutput query="getfairevents" group="eventday">
<div class="schedulebox">
<!--- display event dates --->
<div class="schedulehead" style="clear: both; color: ###daycolor#;">#dateformat(fairdaydate,"dddd, mmmm dd")#</div>
<div class="schedulesubhead" style="clear: both; color: ##ffffff; background: ###daycolor#;">#description#</div>
<!--- event types for current date --->
<cfoutput group="eventtype">
<div class="scheduleitemtitle" style="clear: both; width: 700px; color: ###daycolor#;">#eventtype#</div>
<!--- individual events --->
<cfoutput>
<div class="scheduleitem" style="float: left; width: 75px; text-align: right;"><strong>#LCase(TimeFormat(eventtime,"h:mmtt"))#</strong></div>
<div class="scheduleitem" style="float: left; width: 550px;"> #eventname#</div><br/>
</cfoutput>
</cfoutput>
</div>
</cfoutput>
You're grouping your output on eventday and eventtype. You need to add those two columns to your ORDER BY, otherwise you can get unpredictably-ordered results.
ORDER BY fd.fairDaydate, t.id, ev.eventday, ev.eventtime, ev.eventtype
Ok. I found the problem, and it was a stupid one for me to miss. When I changed that specific entry yesterday, and typed in the correct time, it "auto inserted" the current date. In other words, I typed "8:45pm", and hit enter, and MSSQL automatically converts it to "2014-01-31 19:45:00.000", because yesterday was 01-31-2014. When the data was originally entered, it was 01-23-2014, so all of the entries reflected that date. Because the data type I used for that column was datetime.
I solved the problem by changing the data type to time(7), and viola, all is well. I feel stupid, now.
Thanks to everyone that tried to help with this.
Basically I want to have each child menu only display on the parent menu ID. But so far, all I can get is all of the child li's connecting to any parent menu I set up.
Here is a diagram to explain how the menu is displaying right now:
Home
About > Employment & Mobile (I only want employment to display)
Services > Employment & Mobile (I only want mobile to display)
Contact
So the queries output the following variables from the database
pg_LinkName
pg_MenuTitle
pg_ParentMenu (the name of the parent menu),
pg_MenuType (a yes/no to say if it is a parent/sub menu),
pg_SubMenu (a yes/no to specify whether the menu is a parent menu or not)
I want to know if there's a way to connect the child to the parent dynamically. eg. If I choose to attach a page to a parent, it only shows on that parent in the drop down.
Here are my queries:
<cfquery name="qry_GetMenu" datasource="#request.dsn#">
SELECT *
FROM tbl_pages
WHERE pg_MenuType = TRUE AND pg_Display = TRUE AND pg_AutoMenu = TRUE AND pg_Horiz_VertMenu = TRUE
ORDER BY pg_sort
</cfquery>
<cfquery name="qry_GetSubMenus" datasource="#request.dsn#">
SELECT *
FROM tbl_pages
WHERE pg_MenuType = FALSE
ORDER BY pg_sort
</cfquery>
<cfquery name="qry_SubMenu" datasource="#request.dsn#">
SELECT *
FROM tbl_pages
WHERE pg_SubMenu = TRUE
ORDER BY pg_sort
</cfquery>
And this is what I have for the menu:
<ul class="menu">
<cfoutput query="qry_GetMenu">
<li <cfif cgi.path_info contains "#pg_LinkName#"> class="current-menu-parent"</cfif>>
#pg_MenuTitle#
<cfif pg_SubMenu gt 0>
<ul class="sub-menu">
<cfloop query="qry_GetSubMenus">
<li>#pg_MenuTitle#</li>
</cfloop>
</ul>
</cfif>
</li>
</cfoutput>
</ul>
If I'm understanding correctly, you only want to display the assigned children under the corresponding parent, and your code is currently displaying the child elements under every parent displayed?
With your current code, you would need to move one of your queries in line
<ul class="menu">
<cfoutput query="qry_GetMenu">
<li <cfif cgi.path_info contains "#pg_LinkName#"> class="current-menu-parent"</cfif>>
#pg_MenuTitle#
<cfif pg_SubMenu gt 0>
<ul class="sub-menu">
<!---moved inline to add additional conditional pg_ParentMenu clause--->
<cfquery name="qry_GetSubMenus" datasource="#request.dsn#">
SELECT * FROM q WHERE pg_MenuType = 0 AND pg_ParentMenu = '#pg_ParentMenu#'
</cfquery>
<cfloop query="qry_GetSubMenus">
<li>#pg_MenuTitle#</li>
</cfloop>
</ul>
</cfif>
</li>
</cfoutput>
This would allow the query to be filtered specifically to the current parent menu as opposed to all parent menus. If it is a huge data set, this will become pretty inefficient.
There are lots of options at that point (perform the loops and assign to another object like an array of structs that has the keys for parent and children, with the children being another array, or re-working the database to make the sub-menus relational, etc.).
Hope that is moving in the right direction.
I'm currently struggling to find anyone who knows how this can be done? I've tried a few different methods and ended up with halfway results but not quite what i wanted. Basically i'm trying to create a list showing all the bands A-Z, but the band names are being called from a database, so i'm having to use #band_name# within a nested list. If i re-write the code and post it, someone might be able to see where i'm going wrong.
<cfoutput query="bandNameList">
<cfloop from="65" to="90" index="i">
<UL>
<LI> #chr(i)#
<UL>
<LI> #band_name# </LI>
</UL>
</LI>
</UL>
</cfloop>
</cfoutput>
What I think you're after is to only output the Letter for the first band that begins with that letter.
One way to achieve this is to change your query slightly (note I'm using what I think is SQL-92 syntax here, but there's probably a nicer way to get the first letter in your particular database):
select
band_name,
SUBSTRING(band_name from 1 for 1) AS first_letter
from
bands
order by
band_name
Which will get you the first letter in the query.
If you want to group all the bands with numeric first letters together, then you can use SQL's CASE statement to do that (you may need to find the equivalent to ascii() in your DBMS). You could also invert the logic and match against 'normal' letters and lump everything else into a '0-9 and punctuation' category if that's easier. I think that's what a number of music systems do (I'm thinking iTunes on the iPhone, but I'm sure there are others)
select
band_name,
CASE
WHEN ascii(left(band_name, 1)) BETWEEN 48 AND 57 THEN '0-9'
ELSE left(band_name, 1)
END AS first_letter
from
bands
order by
band_name
Now you can use that extra column along with cfoutput's group attribute to help get the output as you want it.
<UL>
<cfoutput query="bandNameList" group="first_letter">
<LI> #first_letter#
<UL>
<cfoutput>
<LI> #band_name# </LI>
</cfoutput>
</UL>
</LI>
</cfoutput>
</UL>
Update your query to have a left(band_name,1) AS BandStart and make sure to order by band_name in your ORDER BY. Then use group to output the list.
<cfoutput query="bandNameList" group="BandStart">
<UL>
<LI>#bandNameList.BandStart#
<cfoutput>
<UL>
<LI> #bandNameList.band_name# </LI>
</UL>
</cfoutput>
</LI>
</UL>
</cfoutput>
If you want to display all letters, even if no bands starting with that letter exist, another option is using a CTE to generate a table of letters A-Z. Then display the results with a "grouped" cfoutput:
<cfquery name="getBandNameList" ...>
;WITH ltrs ( code ) AS (
SELECT ascii('A') AS code
UNION ALL
SELECT code + 1
FROM ltrs
WHERE ascii('Z') > code
)
SELECT char(code) AS letter, t.band_name
FROM ltrs LEFT JOIN #YourTable t ON t.band_name LIKE char(code) +'%'
ORDER BY letter ASC, t.band_name ASC
</cfquery>
<cfoutput query="bandNameList" group="Letter">
<UL>
<LI> #letter#
<UL>
<cfoutput>
<LI> #band_name# </LI>
</cfoutput>
</UL>
</LI>
</UL>
</cfoutput>
Another approach is to write a sql server stored proc that returns everything in a single query object. The code would resemble this:
declare #thisNum as int
declare #lastNum as int
set #thisNum = 65;
set #lastNum = 90;
declare #letters as table(letter char(1))
while (#thisNum <= #lastNum)
begin
insert into #letters values (CHAR(#thisNum))
set #thisNum = #thisNum + 1;
end
select letter, bandname
from #letters left join band on letter = left(bandname, 1)
order by letter, bandname
Then, in ColdFusion, you can use cfoutput with the group attribute.
Try this code ::
<cfquery datasource="orcl" name="list">
select upper(brand) brand from tbl
</cfquery>
<cfoutput query="list">
<cfloop from="65" to="90" index="i">
<UL>
<LI> #chr(i)#
<UL>
<LI><cfif mid(brand,1,1) eq chr(i)> #brand#</cfif></LI>
</UL>
</LI>
</UL>
</cfloop>
</cfoutput>