【问题标题】:Sorting and Filtering Records排序和过滤记录
【发布时间】:2010-09-22 15:29:47
【问题描述】:

是否有任何已知的模式/算法关于如何以正确的方式执行排序或过滤记录列表(来自数据库)?我目前的尝试涉及使用提供一些过滤和排序选项的表单,然后将这些标准和排序算法附加到我现有的 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 是由脚本逐句生成的)。我正在考虑将所有这些复杂的 SQL 语句都转为视图,这样生成的 SQL 不合适的机会就会减少。

【问题讨论】:

    标签: sql filter sorting


    【解决方案1】:

    这个查询很难理解,因为我必须大量滚动,而且我不知道数据库......

    但是如果特权是“一维的”,例如管理员可以看到所有内容,高级用户可以看到的比管理员少,客人可以看到的比高级用户少,等等:您可能可以在事件和用户中将权限实现为整数,然后

    select from event where conditions AND event.privilegue <= user.privilegue
    

    如果您将权限值设置为 10 000(高/管理员)、5000、1(最低/访客),您可以稍后在两者之间添加更多级别,而无需更改所有代码。

    【讨论】:

    • 条件在这里并不是真正的大问题,我正在寻找一种更好的方法来进行过滤和排序......在sql查询上,它实际上考虑了用户是否可以阅读他的/她的记录,是在正确的类别,正确的状态等记录。
    • 我想我不明白你所说的过滤是什么意思。请解释一下。
    【解决方案2】:

    使用 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
        )
    

    【讨论】:

      【解决方案3】:

      首先,如果您使用联接,此查询的外观和性能会更好:

      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 安全地包含在括号中),因此不可能有人在这些条件之后添加一个条件以某种方式撤消上述条件 - 也就是说,一旦你用一个部分限制了结果子句,如果它与 AND 串在一起,则不能用后面的子句“取消限制”它。 (当然,如果这些附加子句靠近用户文本输入,则必须对其进行清理以防止 SQL 注入攻击。)

      一般来说,数据库的过滤速度比任何其他层都快,因为在数据库上使用 WHERE 子句通常可以让数据库避免从磁盘读取不必要的记录,这比任何其他层都慢几个数量级可以用CPU做。在数据库上排序通常也更快,因为数据库通常可以以这样一种方式进行连接,即记录已经按照您想要的顺序排序。所以,在性能方面,如果你能在数据库上做到这一点,那就更好了。

      您说性能在这里并不是真正的关键,因此以编程方式在业务逻辑中添加过滤器可能对您来说很好,并且比弄乱 SQL 字符串更容易阅读。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-24
        • 2020-11-29
        • 2020-10-07
        • 2017-04-25
        • 2011-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多