如何在mysql过程中编写“WITH CTE AS(SELECT ROW_NUMBER()OVER(ORDER by CASE”)

时间:2013-01-22 13:01:02

标签: mysql sql-server stored-procedures

我有一个SQL Server程序,我需要将它转换为在mysql中工作。

下面是我试过的Mysql转换过程,但它不完整......

DELIMITER $$

DROP PROCEDURE IF EXISTS `SelectjqGridUsers` $$
CREATE PROCEDURE `SelectjqGridUsers` (IN PageIndex INT,IN SortColumnName VARCHAR(50),IN SortOrderBy VARCHAR(4) ,IN NumberOfRows INT ,OUT TotalRecords INT)

BEGIN

 DECLARE StartRow INT;
 DECLARE CTE VARCHAR(100);

 SELECT  TotalRecords = ( SELECT COUNT(1) FROM  Users );

 SET StartRow = (PageIndex * NumberOfRows ) + 1 ;


END $$

DELIMITER ;

这是我最初的SQL Server过程:

CREATE PROC [SelectjqGridUsers]
@PageIndex INT ,
@SortColumnName VARCHAR(50) ,
@SortOrderBy VARCHAR(4) ,
@NumberOfRows INT ,
@TotalRecords INT OUTPUT
AS 
BEGIN

    SET NOCOUNT ON 

    SELECT  @TotalRecords = ( SELECT    COUNT(1)
                              FROM      [Users]
                            )

    DECLARE @StartRow INT
    SET @StartRow = ( @PageIndex * @NumberOfRows ) + 1 ;


    WITH    CTE
              AS ( SELECT   ROW_NUMBER() OVER ( ORDER BY CASE
                                                          WHEN @SortColumnName = 'UserID'
                                                          AND @SortOrderBy = 'asc'
                                                          THEN UserID
                                                         END ASC, CASE
                                                          WHEN @SortColumnName = 'UserID'
                                                          AND @SortOrderBy = 'desc'
                                                          THEN UserID
                                                          END DESC, CASE
                                                          WHEN @SortColumnName = 'UserName'
                                                          AND @SortOrderBy = 'asc'
                                                          THEN UserName
                                                          END ASC, CASE
                                                          WHEN @SortColumnName = 'UserName'
                                                          AND @SortOrderBy = 'desc'
                                                          THEN UserName
                                                          END DESC, CASE
                                                          WHEN @SortColumnName = 'FirstName'
                                                          AND @SortOrderBy = 'asc'
                                                          THEN FirstName
                                                          END ASC, CASE
                                                          WHEN @SortColumnName = 'FirstName'
                                                          AND @SortOrderBy = 'desc'
                                                          THEN FirstName
                                                          END DESC , CASE
                                                          WHEN @SortColumnName = 'MiddleName'
                                                          AND @SortOrderBy = 'asc'
                                                          THEN MiddleName
                                                          END ASC, CASE
                                                          WHEN @SortColumnName = 'MiddleName'
                                                          AND @SortOrderBy = 'desc'
                                                          THEN MiddleName
                                                          END DESC , CASE
                                                          WHEN @SortColumnName = 'LastName'
                                                          AND @SortOrderBy = 'asc'
                                                          THEN LastName
                                                          END ASC, CASE
                                                          WHEN @SortColumnName = 'LastName'
                                                          AND @SortOrderBy = 'desc'
                                                          THEN LastName
                                                          END DESC, CASE
                                                          WHEN @SortColumnName = 'EmailID'
                                                          AND @SortOrderBy = 'asc'
                                                          THEN EmailID
                                                          END ASC, CASE
                                                          WHEN @SortColumnName = 'EmailID'
                                                          AND @SortOrderBy = 'desc'
                                                          THEN EmailID
                                                          END DESC ) AS RN ,
                            UserID ,
                            UserName ,
                            FirstName ,
                            MiddleName ,
                            LastName ,
                            EmailID
                   FROM     [Users]
                 )
        SELECT  UserID ,
                UserName ,
                FirstName ,
                LastName ,
                MiddleName ,
                EmailID
        FROM    CTE
        WHERE   RN BETWEEN @StartRow - @NumberOfRows
                   AND     @StartRow - 1

    SET NOCOUNT OFF


END

有人可以帮我完成这个吗?

1 个答案:

答案 0 :(得分:1)

嗯,首先,在MySQL中没有直接等效的CTE(语句开头的WITH子句)。也没有确切替代ROW_NUMBER()

但是,您可能理解并且(希望)接受这样一个事实:人类语言中的句子并不总是逐字翻译成另一种语言。以同样的方式,用各种SQL编写的SQL查询可能不会也不必转换为子句的不同品种子句。要翻译查询,您需要做两件事,同样重要的是:了解查询使在目标SQL变种中具有多样性。

您正在翻译的存储过程实现了对特定表的动态排序行的动态分页。

关于分页,SQL Server没有本机语法,就像MySQL使用LIMIT ... OFFSET ...功能一样。可能最典型的解决方法,您也可以在这里看到,使用ROW_NUMBER()函数和子选择(在这种情况下,子选择恰好采用CTE的形式)。这是如何运作的? ROW_NUMBER()根据特定的排序条件为子查询中的每一行分配数字,主查询只是过滤这些数字以获取行的范围,从而有效地为您提供页面。 / p>

你在MySQL中不需要任何类型的东西,因为它提供了LIMIT ...OFFSET ...,当它们在存储过程的上下文中使用时,它们都可以接受整数类型的参数或本地整数类型变量作为它们的参数(好吧,它们可以if you are using MySQL 5.5.6+)。

至于动态排序,在SQL Server中,排序必须应用于ROW_NUMBER()函数,因为它与动态分页一起使用。但是在MySQL中,您只需将ROW_NUMBER()的{​​{1}}子句直接移动到(主)查询。

所以,最后,这是我提出的替代存储过程中ORDER BY查询的内容:

SELECT
但是,有一个问题。 SELECT UserID , UserName , FirstName , LastName , MiddleName , EmailID FROM Users ORDER BY CASE WHEN @SortColumnName = 'UserID' AND @SortOrderBy = 'asc' THEN UserID END ASC, CASE WHEN @SortColumnName = 'UserID' AND @SortOrderBy = 'desc' THEN UserID END DESC, CASE WHEN @SortColumnName = 'UserName' AND @SortOrderBy = 'asc' THEN UserName END ASC, CASE WHEN @SortColumnName = 'UserName' AND @SortOrderBy = 'desc' THEN UserName END DESC, CASE WHEN @SortColumnName = 'FirstName' AND @SortOrderBy = 'asc' THEN FirstName END ASC, CASE WHEN @SortColumnName = 'FirstName' AND @SortOrderBy = 'desc' THEN FirstName END DESC, CASE WHEN @SortColumnName = 'MiddleName' AND @SortOrderBy = 'asc' THEN MiddleName END ASC, CASE WHEN @SortColumnName = 'MiddleName' AND @SortOrderBy = 'desc' THEN MiddleName END DESC, CASE WHEN @SortColumnName = 'LastName' AND @SortOrderBy = 'asc' THEN LastName END ASC, CASE WHEN @SortColumnName = 'LastName' AND @SortOrderBy = 'desc' THEN LastName END DESC, CASE WHEN @SortColumnName = 'EmailID' AND @SortOrderBy = 'asc' THEN EmailID END ASC, CASE WHEN @SortColumnName = 'EmailID' AND @SortOrderBy = 'desc' THEN EmailID END DESC LIMIT NumberOfRows OFFSET StartRow ; LIMIT的参数化只能以引用(对参数或变量)的形式完成,即您不能使用表达式< / em>那里。所以,我不得不简单地使用上面的OFFSET。但是,它将为您提供与SQL Server版本返回的页面不同的页面,除非您还更改OFFSET StartRow语句,如下所示:

SET StartRow