【问题标题】:SQL reduce the amout of selects on tableSQL减少对表的选择量
【发布时间】:2015-12-02 11:08:50
【问题描述】:

我的 SQL 查询存在性能问题:(在 Oracle SQL 上)

Data:
- step:number
- processid:number
- Status:number
- process_planed:number

- id:primary
- ... and many more

专用于特定 processid (4711) 的所有行的结果:

step   |processid  |Status   |Process_planned |....
---------------------------------------------------
10     |4711       |30       | 75             |....
20     |4711       |50       | 81             |....
30     |4711       |10       | 81             |....
40     |4711       |10       | 36             |....
50     |4711       |10       | 25             |....

我的数据库中充满了此类数据。问题是,步长值不是固定的。也可以是:

260,310,570,600 ...

现在我想获取 process_planned = 75 和 Status = 10 的每个数据,但我只想要这些进程,它们的第一个条目(在上面的步骤 10 中的示例)等于 10。我的解决方案如下:

  • 1 个查询,用于获取 process_planned = 75 和不同 processid 的所有行
  • 现在我有所有涉及到 process_id = 75 的进程
  • 然后我为每个 process_id 做一个子查询,它检查第一步是否与 process_planned = 75 以及 Status = 10 相关
  • 然后我将这个单一数据写入一个数组。

现在的问题是我的解决方案缺乏性能!例如40 个 processid,每 6 个步骤我对我的解决方案执行 241 个查询!必须有更简单的方法来做到这一点。

但我不知道,如果步骤被修复会很容易,那么只需添加 where step = 10 即可获得最初的步骤。

你有什么想法吗?

【问题讨论】:

    标签: oracle11g query-performance


    【解决方案1】:

    您是否尝试过使用ROW_NUMBER 来查找每个进程ID 的第一条记录?

    您可以使用行号对每个进程 ID 的返回记录进行排名。然后,您可以筛选出最高排名。

    Example

    WITH SampleDate AS
        (
            /* This CTE returns some example records.
             */
            SELECT
                r.*
            FROM
                (
                    VALUES    
                        (10, 4711, 30, 75),
                        (20, 4711, 50, 81),
                        (30, 4711, 10, 75),
                        (40, 4711, 10, 75),
                        (50, 4711, 10, 25)
                ) AS r(Step, ProcessId, [Status], Processed_Planned)
        )
    /* Main query returns the first row for 
     * each process id with a planned of 75
     * and a status of 10.
     */
    SELECT
        r.*
    FROM
        (
            /* This sub query ranks the steps from each 
             * procsss id.
             */
            SELECT
                ROW_NUMBER() OVER(PARTITION BY ProcessId ORDER BY Step) AS RowNumber,
                *
            FROM
                SampleDate
            WHERE
                Processed_Planned = 75
                AND [Status] = 10
        ) AS r
    WHERE
        RowNumber = 1 
    ;
    

    【讨论】:

    • 感谢您的快速回答:我已经根据我的需求更改了代码,但我得到了以下异常:“缺少右括号”我应该说,我使用 Oracle sql
    • 听起来像是错字。您的代码中可能有一个以上(比)。我在 SQL Server 中测试了该示例。 ROW_NUMBER 的 Oracle 文档可以在下面找到。不确定是否有任何差异。您可能应该从标签中删除 SQL Server。它增加了收到答案的几率,而不是对您不起作用。 docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm
    【解决方案2】:

    我认为您要求step 的最小值,其中process_planned = 75status = 10,在这种情况下您可以这样做

    SELECT MIN(step) AS step, processid, status, process_planned
    FROM data
    WHERE process_planned = 75 AND status = 10
    GROUP BY processid, status, process_planned;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-22
      • 2020-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 2021-09-16
      相关资源
      最近更新 更多