服务台数据库设计(Help Desk Database Design)

我所在的公司对于服务台系统有着非常特殊和独特的需求,所以没有任何开源系统能够为我们工作。 既然如此,我使用PHP和MySQL创建了一个自定义系统。 它远非完美,但比上一次使用的系统要好得多。 相信我! 它很好地满足了我们大部分的需求,但是我对数据库设置的方式有疑问。 这里是主要表格:

ClosedTickets
ClosedTicketSolutions
Locations
OpenTickets
OpenTicketSolutions
Statuses
Technicians

当用户提交帮助请求时,它将进入“OpenTickets”表。 当技术人员处理这个问题时,他们会提交条目并描述他们所做的事情。 这些条目放在“OpenTicketSolutions”表中。 问题解决后,处理该问题的最后一位技术人员将关闭该故障单并将其移至“ClosedTickets”表。 所有解决方案条目也都移到“ClosedTicketSolutions”表中。 其他表(位置,状态和技术人员)作为标准化手段存在(每个位置,状态和技术人员都有一个被引用的ID)。

我现在遇到的问题是这样的:

当我想查看所有打开的故障单的列表时,SQL语句有点复杂,因为我必须离开“位置”,“状态”和“技术人员”表。 来自各种表格的字段也需要可搜索。 查看SQL语句搜索由任何名字中包含“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

我现在无法做的一件事是同时搜索开放票和封闭票。 我不认为工会会适用于我的案子。 所以我想知道是否应该将打开和关闭的票据存储在同一个表中,并且只需要一个指示是否关闭票证的字段。 我可以预见的唯一问题是我们已经有很多已关闭的门票(将近30,000个),因此整个系统可能会执行得很慢。 将开放票和封闭票结合起来会不是个好主意?


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?


原文:https://stackoverflow.com/questions/2539986
2023-11-01 17:11

满意答案

aggregate是你的答案

db.foo.aggregate({"$project" : {"two" : "$friends.two"}}).result

还有另一种方法可以做到这一点(获得不同的价值)

db.foo.aggregate([      
    {'$project': {  
                    union:{$setUnion:["$friends.two"]}
                 }
    }
]).result;

aggregate is your answer

db.foo.aggregate({"$project" : {"two" : "$friends.two"}}).result

there is another way to do that (getting distinct values)

db.foo.aggregate([      
    {'$project': {  
                    union:{$setUnion:["$friends.two"]}
                 }
    }
]).result;

相关问答

更多

MongoDB部分匹配对象(MongoDB partial match on object)

我认为这应该工作: db.tutorials.find({ $or: [ { "permissions.records": { $elemMatch: { $in: ["add", "delete"] } } }, { "permissions.folders": { $elemMatch: { $in: ["delete"] } } }, { "permissions.logs": { $elemMatch: { $in: ["add", ...

如何从mongodb中的字段中的对象数组中检索部分对象(how to retrieve partial objects from object array in a field in mongodb)

aggregate是你的答案 db.foo.aggregate({"$project" : {"two" : "$friends.two"}}).result 还有另一种方法可以做到这一点(获得不同的价值) db.foo.aggregate([ {'$project': { union:{$setUnion:["$friends.two"]} } } ]).result; aggregat...

使用mongodb中对象字段的值创建新的数组字段(Create new array field with values from object field in mongodb)

我所要做的就是将一个函数传递给db.eval,如下所示: db.eval(function() {db.test.find({ class: 'x' }).snapshot().forEach( function (e) { e.urls2 = [{ url: e.urls.a, type: 'a'}]; db.test.save(e); } )}) 它工作 All I had to do was to pass a function to db.eval, like t...

在mongoDB中如何达到对象数组中字段“name”的值(In mongoDB how to reach to value of the field “name” in the array of objects)

您可以通过提供嵌套属性的路径来搜索mongodb中的嵌套对象: db.YOURCOLLECTION.find({"friends.name": "ABC"}); 在这里阅读更多关于嵌套对象查询 也许这个领域需要在这个领域执行搜索之前索引? 当然你可以在嵌套字段上创建索引。 只要提供一个带有属性的索引就像上面的嵌套字段的路径: db.YOURCOLLECTION.createIndex( { "friends.name": 1 } ) 为了提前使用,您可以阅读$regex查询 You can s...

查询文档中的特定对象和可视化 - MongoDB [重复](Querying for specific objects in a document & Visualization - MongoDB [duplicate])

find(arg1) 命令您使用返回与存储在集合中的文档,因此它可以搜索嵌套的文档,但不能返回顶级集合文档的一部分。 它返回所有文档。 如果你的文档结构经常尝试使用它 find(arg1, arg2) 而是限制返回的字段https://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/ 如果您的文档结构不规则,请使用您喜欢的编程语言编写脚本 After much research, I found a way ...

检索MongoDB集合中对象数组中的查询元素(Retrieve the queried element in an object array in MongoDB collection)

使用Mongo 2.2+,您可以使用新的聚合框架 。 db.getCollection('models').aggregate([ { $unwind : "$grades.grades" }, { $match : {"dataPath": "/nissan/in/en/L02B", "grades.grades.key": "LVL002"}} ]) 展开从输入解构数组字段以输出每个元素的文档。 使用您发布的文档作为示例,通过展开,您将有4个...

MongoDB对象数组查询[重复](MongoDB array of objects query [duplicate])

嗨,你可以使用$ elemMatch来做到这一点。 这是一个工作样本 db.getCollection('users').find( {"cars": {$elemMatch: { "type": "hatchback","score": {$gte: 6} } } } ) 正如您所看到的,$ elemMatch的语法是 { <field>: { $elemMatch: { <query1>, <...

如何查询和删除MongoDB中数组字段中的嵌入对象?(How to query for and delete embedded objects in an array field in MongoDB?)

您可以将文档重组为此结构: { "_id" : ObjectId("581114330de9ac0c1445cdd6"), "user" : "test-username1", "likedQuizzes" : [ { "title" : "2 Purple", "author" : "purple-tester1", "date" : ISODate("2016-10-26T20:39...

FluentNhibernate,检索部分对象图(FluentNhibernate, retrieve partial Object Graph)

这实际上取决于你想要对订单做什么。 您是否需要查询聚合根? 相反,按日期查询实际订单是否有意义? 所以你最终得到: session.QueryOver<Order>().Where(t => t.OrderDate > ...); 如果您的关联设置正确,您仍然可以导航到该用户。 我个人认为存储库模式有点限制,宁愿使用查询对象,所以你最终得到的结果如下: queryService.FindAll<UserGroup>(new GetAllByFilterOrderDate(DateTime.Now...

查询数组中的部分对象 - MongoDB(Query for Partial Object in Array - MongoDB)

根据高级查询文档 ,您可以使用点表示法混合数组值查询以进入对象 。 以下是使用您的架构的示例: $ mongo MongoDB shell version: 2.1.0 connecting to: test > db.users.save({_id: 1, friends: [{id: 2, name: 'bob'}]}) > db.users.find({friends: {id: 2, name: 'bob'}}) { "_id" : 1, "friends" : [ { "id" : 2,...

相关文章

更多

HTML5 Web SQL Database 数据库

Web SQL数据库API实际上不是HTML5规范的组成部分,而是单独的规范。它通过一套API来操纵客 ...

HDFS Append 设计文档的QA(Questions about the “Append Design”)

本文是关于Append设计文档中一些设计点的QA,原文的地址已经不记得是从HDFS中的那个Jira上看 ...

myEclipse8.5 New DataBase Connection Driver时出错

大侠看看,菜鸟求教。 这个密码指的是什么密码? 我把可能的秘密输出后有弹出这样的框, 问题补充 ...

腾讯高级设计师谈微信的旧容与新妆,Android Design是大势所趋

编者按:本篇投稿选自腾讯大讲堂(更多腾讯产品技术文章,可以关注“腾讯大讲堂”微信公众账号),由腾讯研发 ...

《Oracle Database 11g DBA手册》(Oracle Database 11g DBA Handbook )扫描版[PDF]

中文名: Oracle Database 11g DBA手册 原名: Oracle Databa ...

《Oracle Database 11g SQL开发指南》(Oracle Database 11g SQL )扫描版[PDF]

中文名: Oracle Database 11g SQL开发指南 原名: Oracle Data ...

《数据库系统基础:初级篇(第5版)》(Fundamentals of Database Systems (5th Edition))扫描版[PDF]

中文名: 数据库系统基础:初级篇(第5版) 原名: Fundamentals of Databa ...

《数据库系统基础:高级篇(第5版)》(Fundamentals of Database Systems (5th Edition) )扫描版[PDF]

中文名: 数据库系统基础:高级篇(第5版) 原名: Fundamentals of Databa ...

数据库设计 Step by Step (1)

引言:一直在从事数据库开发和设计工作,也看了一些书籍,算是略有心得。很久之前就想针对关系数据库设计进行 ...

电商平台数据库设计

电商平台数据库表设计:商品分类表、商品信息表、品牌表、商品属性表、商品属性扩展表、规格表、规格扩展表

最新问答

更多

获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)

我用Google搜索了一个解决方案。 “EnumDisplayModeProvider”是我自己设置网站的各种模式的枚举。 public EnumDisplayModeProvider GetDisplayModeId() { foreach (var mode in DisplayModeProvider.Instance.Modes) if (mode.CanHandleContext(HttpContext)) {

如何通过引用返回对象?(How is returning an object by reference possible?)

这相对简单:在类的构造函数中,您可以分配内存,例如使用new 。 如果你制作一个对象的副本,你不是每次都分配新的内存,而是只复制指向原始内存块的指针,同时递增一个也存储在内存中的引用计数器,使得每个副本都是对象可以访问它。 如果引用计数降至零,则销毁对象将减少引用计数并仅释放分配的内存。 您只需要一个自定义复制构造函数和赋值运算符。 这基本上是共享指针的工作方式。 This is relatively easy: In the class' constructor, you allocate m

矩阵如何存储在内存中?(How are matrices stored in memory?)

正如它在“熵编码”中所说的那样,使用Z字形图案,与RLE一起使用,在许多情况下,RLE已经减小了尺寸。 但是,据我所知,DCT本身并没有给出稀疏矩阵。 但它通常会增强矩阵的熵。 这是compressen变得有损的点:输入矩阵用DCT传输,然后量化量化然后使用霍夫曼编码。 As it says in "Entropy coding" a zig-zag pattern is used, together with RLE which will already reduce size for man

每个请求的Java新会话?(Java New Session For Each Request?)

你是如何进行重定向的? 您是否事先调用了HttpServletResponse.encodeRedirectURL()? 在这里阅读javadoc 您可以使用它像response.sendRedirect(response.encodeRedirectURL(path)); The issue was with the path in the JSESSIONID cookie. I still can't figure out why it was being set to the tomca

css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)

我认为word-break ,如果你想在一个单词中打破行,你可以指定它,这样做可以解决问题: .column { word-break:break-all; } jsFiddle演示。 您可以在此处阅读有关word-break属性的更多信息。 I think word-break, with which you can specify if you want to break line within a word, will do the trick: .column { word-break

无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)

我认为您忘记在分类时间内缩放输入图像,如train_test.prototxt文件的第11行所示。 您可能应该在C ++代码中的某个位置乘以该因子,或者使用Caffe图层来缩放输入(请查看ELTWISE或POWER图层)。 编辑: 在评论中进行了一次对话之后,结果发现在classification.cpp文件中错误地删除了图像均值,而在原始训练/测试管道中没有减去图像均值。 I think you have forgotten to scale the input image during cl

xcode语法颜色编码解释?(xcode syntax color coding explained?)

转到: Xcode => Preferences => Fonts & Colors 您将看到每个语法高亮颜色旁边都有一个简短的解释。 Go to: Xcode => Preferences => Fonts & Colors You'll see that each syntax highlighting colour has a brief explanation next to it.

在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)

你考虑过第三方拼写检查吗? 您可以将在C#中开发的自定义WinForms控件插入访问数据库吗? VB6控件怎么样? 如果你能找到一个使用第三方库进行拼写检查的控件,那可能会有效。 Have you considered a third party spell checker? Can you insert a custom WinForms controls developed in C# into an access database? What about a VB6 control? If

从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)

我有同样的问题,因为我在远程服务器上有两个图像,我需要在每天的预定义时间复制到我的本地服务器,这是我能够提出的代码... try { if(@copy('url/to/source/image.ext', 'local/absolute/path/on/server/' . date("d-m-Y") . ".gif")) { } else { $errors = error_get_last(); throw new Exception($err

从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))

我不确定我完全明白你在说什么。 你能编辑你的帖子并包含你正在做的Subversion命令/操作的特定顺序吗? 最好使用命令行svn客户端,以便容易为其他人重现问题。 如果您只是想获取文件的旧副本(即使该文件不再存在),您可以使用如下命令: svn copy ${repo}/trunk/moduleA/file1@${rev} ${repo}/trunk/moduleB/file1 其中${repo}是您的存储库的URL, ${rev}是您想要的文件的版本。 这将恢复该文件的旧版本,包括最高版本