views:

143

answers:

3

The company I work at has very specific and unique needs for a help desk system, so none of the open source systems will work for us. That being the case, I created a custom system using PHP and MySQL. It's far from perfect, but it's infinitely better than the last system they were using; trust me! It meets most of our needs quite nicely, but I have a question about the way I have the database set up. Here are the main tables:

ClosedTickets
ClosedTicketSolutions
Locations
OpenTickets
OpenTicketSolutions
Statuses
Technicians

When a user submits a help request, it goes in the "OpenTickets" table. As the technicians work on the problem, they submit entries with a description of what they've done. These entries go in the "OpenTicketSolutions" table. When the problem has been resolved, the last technician to work on the problem closes the ticket and it gets moved to the "ClosedTickets" table. All of the solution entries get moved to the "ClosedTicketSolutions" table as well. The other tables (Locations, Statuses, and Technicians) exist as a means of normalization (each location, status, and technician has an ID which is referenced).

The problem I'm having now is this:

When I want to view a list of all the open tickets, the SQL statement is somewhat complicated because I have to left join the "Locations", "Statuses", and "Technicians" tables. Fields from various tables need to be searchable as well. Check out how complicated the SQL statement is to search closed tickets for tickets submitted by anybody with a first name containing "John":


SELECT ClosedTickets.*, date_format(ClosedTickets.EntryDate, '%c/%e/%y %l:%i %p') AS Formatted_Date, date_format(ClosedDate, '%c/%e/%y %l:%i %p') AS Formatted_ClosedDate, Concat(Technicians.LastName, ', ', Technicians.FirstName) AS TechFullName, Locations.LocationName, date_format(ClosedTicketSolutions.EntryDate, '%c/%e/%y') AS Formatted_Solution_EntryDate, ClosedTicketSolutions.HoursSpent AS SolutionHoursSpent, ClosedTicketSolutions.Tech_ID AS SolutionTech_ID, ClosedTicketSolutions.EntryText
FROM ClosedTickets
LEFT JOIN Technicians ON ClosedTickets.Tech_ID = Technicians.Tech_ID
LEFT JOIN Locations ON ClosedTickets.Location_ID = Locations.Location_ID
LEFT JOIN ClosedTicketSolutions ON ClosedTickets.TicketNum = ClosedTicketSolutions.TicketNum
WHERE (ClosedTickets.FirstName LIKE '%John%')
ORDER BY ClosedDate Desc, ClosedTicketSolutions.EntryDate, ClosedTicketSolutions.Entry_ID

One thing that I'm not able to do right now is search both open and closed tickets at the same time. I don't think a union would work in my case. So I'm wondering if I should store the open and closed tickets in the same table and just have a field indicating whether or not the ticket is closed. The only problem I can forsee is that we have so many closed tickets already (nearly 30,000) so the whole system might perform slowly. Would it be a bad idea to combine the open and closed tickets?

+2  A: 

I would store them int he same table. Partitioning them into two tables only as an optimization if there were a lot of tickets. I doubt this will be a problem though.

30,000 really is small in the grand scheme. Databases are built to handle millions of rows without breaking a sweat. So long as you have proper indexing (all join columns and potential search columns).

Down the road if you start experience slow-downs, start archiving older tickets into a archive table.

Overall the one table design is cleaner and keeps like data together.

vfilby
elduff
Thank you, vfilby! If I were to need to archive tickets into another table, would I search both at the same time using a union?
Adam
Honestly, I'd try to avoid having two tables with the same schema and data, but you could search them using a union. If the union is really slow try 'Union All'. Union by default uses a distinct, union all doesn't and is faster. Depending on the technology you have other options too. I believe in sql server you can actually control table partition (how it's stored) to make it more efficient. That's DBA land though, beyond my knowledge.
vfilby
A: 

Why do you have 4 tables for tickets? I would associate one table for tickets and another for ticket solutions.

Mike
There are two tables for tickets and two tables for solution entries for the tickets. This way, multiple technicians can participate input solution information.
Adam
then just add another table with solution info, the ticketid, the technicianid, and there is your multiple relation table.
Mike
and a closed/open boolean. You can then consolidate two tables into one.
Mike
A: 

I think it would be advisable to store both open and closed tickets in one table. You can create a Status field with values of 0 for closed, 1 for open, or whatever convention you want to use. As another answerer mentioned, 30k records should not be a problem.

Hope this helps.

SidC
Thank you! I will do that.
Adam