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

Bea*_*ead 3 php sql db2 pagination

现在我做两个单独的SQL语句,一个SELECT COUNT(*)基本上与搜索语句相同的标准.我不是最好的做出这些陈述,有时候有点慢,我想知道是否有更好的方法来做我做的事情.可能只在PHP中执行一个SQL语句和一些其他工作?这是一个示例"搜索包含"我有声明.

在第二个语句中,您将看到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%') 
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Clo*_*use 6

如果您试图显示结果的总计数以及分页计数(因此38中的0到25),单独的声明可能是您最好的选择.我尝试了很多方法来计算各行的数量,但性能(即使在温和的测试数据库上)也很糟糕.

你可能应该做的是创建一个你可以查询的视图,其中包含你所有的选择标准,然后用必要的行为包装它:
Count:

SELECT COUNT(*)
FROM view
Run Code Online (Sandbox Code Playgroud)

排名行:

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

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

如果您实际上不需要提前知道总行数,则可以简单地将结束等级设置为起始等级加上一些偏移量.然后,当您使用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
Run Code Online (Sandbox Code Playgroud)

当然,你仍然必须where在子选择中定义你的子句......