是否有任何关于如何以正确方式对记录列表(来自数据库)进行排序或过滤的已知模式/算法?我当前的尝试涉及使用提供一些过滤和排序选项的表单,然后将这些标准和排序算法附加到我现有的SQL。但是,我发现很容易被滥用,用户可能会得到他们不希望看到的结果。
我正在构建的应用程序是一个调度程序,我将所有事件存储在数据库表中。然后,根据用户的级别/角色/权限,将显示不同的数据子集。因此,我的查询可能与
一样复杂SELECT *
FROM app_event._event_view
WHERE ((class_id = (SELECT class_id FROM app_event._ical_class WHERE name = 'PUBLIC') AND class_id != (SELECT class_id FROM app_event._ical_class WHERE name = 'PRIVATE') AND class_id != (SELECT class_id FROM app_event._ical_class WHERE name = 'CONFIDENTIAL')) OR user_id = '1')
AND calendar_id IN (SELECT calendar_id FROM app_event.calendar WHERE is_personal = 't')
AND calendar_id = (SELECT calendar_id FROM app_event.calendar WHERE name = 'personal')
AND state_id IN (1,2,3,4,5,6) AND EXTRACT(year FROM dtstart) = '2008'
AND EXTRACT(month FROM dtstart) = '11'
由于我更关心提供正确的信息子集,因此性能目前不是主要关注点(因为提到的sql是由脚本生成的,by clause子句)。我正在考虑将所有这些复杂的SQL语句转换为视图,因此SQL生成的机会不太合适。
答案 0 :(得分:1)
首先,如果您使用连接,此查询将会更好看并执行:
SELECT *
FROM
app_event._event_view EV
INNER JOIN app_event.calendar C
ON EV.calendar_id = C.calendar.id
INNER JOIN app_event._ical_class IC
ON C.class_id = EV.class_id
WHERE
C.is_personal = 't'
AND C.name = 'personal'
AND state_id IN (1,2,3,4,5,6)
AND EXTRACT(year FROM dtstart) = '2008'
AND EXTRACT(month FROM dtstart) = '11'
AND (
IC.name = 'PUBLIC' -- other two are redundant
OR user_id = '1'
)
这是降低复杂性的良好开端。然后,如果要直接向SQL添加其他过滤器,可以在末尾附加更多“AND ...”语句。由于所有标准都与AND相关(OR被安全地包含在括号内),因此不可能有人在这些之后添加一个标准,以某种方式解除上面的标准 - 也就是说,一旦你用一个部分限制了结果如果它与ANDs串在一起,你不能用后面的句子“解除限制”它。 (当然,如果这些附加条款接近用户文本输入,则必须对它们进行清理以防止SQL注入攻击。)
一般情况下,数据库可以比任何其他层过滤得更快,因为在数据库上使用WHERE子句通常会让数据库甚至无法从磁盘上读取不必要的记录,这比你的任何东西慢几个数量级可以用CPU做。数据库上的排序通常也更快,因为数据库通常可以以记录已按您希望的顺序排序的方式进行连接。所以,性能方面,如果你能在数据库上做到这一点,那就更好了。
你说性能并不是真正关键的,所以在业务逻辑中以编程方式添加过滤器对你来说可能没问题,而且比乱用SQL字符串更容易阅读。
答案 1 :(得分:0)
很难理解这个查询,因为我必须大量滚动,因为我不知道数据库......
但如果特权是“一维的”,例如管理员可以看到所有内容,高级用户可以看到少于管理员,客户可以看到少于高级用户等等。您可以在事件和用户中将权限实现为整数,然后
select from event where conditions AND event.privilegue <= user.privilegue
如果您将特权值设置为10 000(高/管理员),5000,1(最低/客人),您可以稍后在不更改所有代码的情况下在其间添加更多级别。
答案 2 :(得分:0)
使用ORM工具或使用如下参数:
SELECT *
FROM app_event._event_view
WHERE
(
:p_start_year is null or
(state_id IN (1,2,3,4,5,6) AND EXTRACT(year FROM dtstart) = :p_start_year)
)
and
(
:p_date_start is null or
AND EXTRACT(month FROM dtstart) = :p_date_start
)