小编典典

使用SQL搜索DB2进行分页的最快,最高效的方法

sql

现在,我执行两个单独的SQL语句,一个执行SELECT COUNT(*)与搜索语句基本相同的条件。我并不是最擅长做出这些陈述,有时会有点慢,我想知道是否有更好的方法来做我所做的事情。可能只执行一个SQL语句,并在PHP中做更多工作?这是我有陈述的“搜索包含”示例。

在第二条语句中,您将看到Y之间的X,这部分是由第一行计数语句的结果计算得出的。

SQL行数:

SELECT COUNT(*) 
FROM itemmast 
LEFT OUTER JOIN itemweb 
ON iline = line 
AND iitem = item 
JOIN linemst 
ON iline = lline 
LEFT OUTER JOIN custord 
ON opline = iline 
AND opitem = iitem 
AND opcust = '12345' 
LEFT OUTER JOIN ordwdtl 
ON owline = iline 
AND owitem = iitem 
AND owusr ='user' 
AND owcust ='12345' 
WHERE ico = 01 
AND iecomm = 'Y'  
AND (UPPER(ITEMDESC) || UPPER(PRODDESC)) LIKE '%FOO%' 
     OR LINE LIKE '%FOO%' 
     OR UPPER(MFGNAME) LIKE '%FOO%' 
     OR UPPER(ITEM) LIKE '%FOO%' 
     OR UPPER(PRODNAME) LIKE '%FOO%' 
     OR UPPER(IDESC1 || IDESC2) LIKE '%FOO%' 
     OR UPPER(IMFGNO) LIKE '%FOO%' 
     OR UPPER(IITEM) LIKE '%FOO%')

SQL搜索:

SELECT * 
FROM (SELECT iline AS line, iitem AS item, rownumber() OVER (ORDER BY item) AS ROW_NUM 
      FROM itemmast 
      LEFT OUTER JOIN itemweb 
      ON iline = line 
      AND iitem = item 
      JOIN linemst 
      ON iline = lline 
      LEFT OUTER JOIN custord 
      ON opline = iline 
      AND opitem = iitem 
      AND opcust = '12345' 
      LEFT OUTER JOIN ordwdtl 
      ON owline = iline 
      AND owitem = iitem 
      AND owusr = 'user' 
      AND owcust = '12345' 
      WHERE ico = 01 
      AND iecomm = 'Y' 
      AND (UPPER(ITEMDESC) || UPPER(PRODDESC)) LIKE '%FOO%' 
           OR LINE LIKE '%FOO%' 
           OR UPPER(MFGNAME) LIKE '%FOO%' 
           OR UPPER(ITEM) LIKE '%FOO%' 
           OR UPPER(PRODNAME) LIKE '%FOO%' 
           OR UPPER(IDESC1 || IDESC2) LIKE '%FOO%' 
           OR UPPER(IMFGNO) LIKE '%FOO%' 
           OR UPPER(IITEM) LIKE '%FOO%')) 
      AS TEMP 
WHERE ROW_NUM BETWEEN 0 AND 25

阅读 215

收藏
2021-04-07

共1个答案

小编典典

如果您要显示结果的总计数和分页计数(因此38中为‘0到25’),那么最好的选择是单独声明。我已经尝试了很多方法来获取各个行旁边的计数,但是性能(即使在中等测试数据库上)也很糟糕。

您可能应该做的是创建一个可以查询的视图,其中包含所有选择条件,然后将其包装为必需的行为即可:
Count:

SELECT COUNT(*)
FROM view

排名行:

SELECT *
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY item) as RANK
      FROM view) as TEMP
WHERE RANK BETWEEN 0 AND 25

您当然需要添加相对where条件,但这是视图要处理的事物类型。

如果您实际上不需要提前知道总行数,则只需将最终排名设置为开始排名加上一些偏移即可。然后,当您使用PHP显示结果时,只需编辑结尾显示值。

一些随机的注释:1)是否有line不是upper()d的原因?
2)仅仅因为所有的字符串操作/比较,此查询的性能几乎将受到影响,无论您做什么。是否有可能消除或忽略某些条件?除非已将用于各种字符串列的索引upper应用于它们(某些更高版本的DB2允许将某些标量函数应用于索引键),否则大多数索引将完全无用(这并不能帮助您“重新寻找%ANYTHING%毕竟)。


好的,有一种“棘手”的方法可以执行类似的操作,并且似乎可以获得良好的性能…尝试这样的操作(首先定义一个视图确实会有所帮助):

SELECT TEMP.*, CASE WHEN RANK = 0 THEN (SELECT COUNT(*)
                                        FROM view)
                    ELSE 0 END
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY item) as RANK
      FROM view) as TEMP
WHERE RANK BETWEEN 0 AND 25

当然,您仍然必须where在subselect中定义您的子句…

2021-04-07