同一查询使用row_number()

时间:2018-07-18 09:29:57

标签: sql sql-server database

假设我有两个桌子。第一个表代表帐户,第二个表代表字符。表通过“ AccountId”列连接。根据游戏,字符连接到帐户,每个帐户可以包含4个字符。

在我的网站上,我有两个页面。第一页称为“ Characterlist.php”,并使用一个等于0的特定权限(帐户表中的列)生成游戏中的所有角色。

我正在使用此查询:

$query = "WITH 
        Acc AS 
          (SELECT AccountId, Authority 
           FROM Account 
           WHERE Authority = '0'),
        Char AS 
          (SELECT Character.* 
          FROM Character, Acc 
          WHERE Character.AccountId = Acc.AccountId),
        Res AS 
         (SELECT *, 
         ROW_NUMBER() OVER 
        (ORDER BY Reput DESC) AS row_number 
         FROM Char)
    SELECT Res.Class, 
           Res.Name, 
           Res.Level, 
           Res.HeroLevel, 
           Res.Reput, 
           Res.row_number 
      FROM Res 
      WHERE Res.row_number >= '$charlistpagemin' 
      AND Res.row_number <= '$charlistpagemax'";

$ charlistpagemin和$ vharlistpagemax是我用来将整个字符列表分为几页的php变量。

当我搜索我的测试帐户的字符时,根据row_number()生成和排序的信誉的位置是可以的。

然后我有第二页userpanel.php,该页面仅显示给已签名的用户,使他们可以在另一个列表中看到他们的游戏角色。

我使用的查询几乎相同,但最终使用不同的规则。

$query = 
"WITH 
 Acc AS 
    (SELECT AccountId, 
     Authority 
     FROM Account 
     WHERE Authority = '0'),
  Char AS 
     (SELECT Character.* 
      FROM Character, Acc 
      WHERE Character.AccountId = Acc.AccountId),
  Res AS 
     (SELECT *, 
      ROW_NUMBER() 
      OVER (ORDER BY Reput DESC) AS row_number FROM Char)
SELECT Res.AccountId, 
       Res.Class, 
       Res.Name, 
       Res.Level, 
       Res.HeroLevel, 
       Res.Reput, 
       Res.row_number 
  FROM Res 
  WHERE Res.AccountId = '" . $_SESSION["accountid"] . "'";

有问题。根据信誉,它们的位置与characterlist.php中的位置不同(不好)。问题出在哪里?

编辑: 表格“帐户”如下所示:

AccountId | Authority | ... |

“字符”表如下所示:

AccountId | Class | Name | Level | HeroLevel | Reput | ... |

我的测试帐户具有

AccountId: xxx | Authority: 0 | ... | 

并且有字符

AccountId: XXX | Class: Dobrodruh | Name: Kryploij1 | Level: 15 | Herolevel: 0 | Reput: 0 | ... |
AccountId: XXX | Class: Dobrodruh | Name: Kryploid2 | Level: 15 | Herolevel: 0 | Reput: 0 | ... |
AccountId: XXX | Class: Dobrodruh | Name: Kryploij3 | Level: 15 | Herolevel: 0 | Reput: 0 | ... |
AccountId: XXX | Class: Dobrodruh | Name: Grakonecek<3 | Level: 15 | Herolevel: 0 | Reput: 0 | ... |

characterlist.php中显示的预期结果是

Position: 139 | Class: Dobrodruh | Name: Kryploij1 | Level: 15 | Herolevel: 0 | Reput: 0 |
Position: 140 | Class: Dobrodruh | Name: Kryploid2 | Level: 15 | Herolevel: 0 | Reput: 0 |
Position: 141 | Class: Dobrodruh | Name: Kryploij3 | Level: 15 | Herolevel: 0 | Reput: 0 |
Position: 142 | Class: Dobrodruh | Name: Grakonecek<3 | Level: 15 | Herolevel: 0 | Reput: 0 |

但是userpanel.php的不良结果是:

Position: 110 | Class: Dobrodruh | Name: Kryploij1 | Level: 15 | Herolevel: 0 | Reput: 0 |
Position: 111 | Class: Dobrodruh | Name: Kryploid2 | Level: 15 | Herolevel: 0 | Reput: 0 |
Position: 112 | Class: Dobrodruh | Name: Kryploij3 | Level: 15 | Herolevel: 0 | Reput: 0 |
Position: 113 | Class: Dobrodruh | Name: Grakonecek<3 | Level: 15 | Herolevel: 0 | Reput: 0 |

简单来说,我的问题是用户面板的位置发生了变化。真实位置显示在字符列表中。为了根据信誉中表中的排序数据计算排名,我使用了查询中显示的row_number()函数。

2 个答案:

答案 0 :(得分:1)

您的数据与reput有联系,而您的row_number()表达式为:

ROW_NUMBER() OVER (ORDER BY Reput DESC) AS row_number

在SQL中的订单是不稳定。这意味着具有联系的行以任意且不确定的顺序进行,并且该顺序可能从一个执行更改为另一个执行。

为什么排序不稳定?简单。 SQL表表示无序集,因此没有“基础”排序来定义在发生联系时发生的情况。

简单的解决方案是添加另一个密钥。对于您而言,我认为Name可能就足够了:

ROW_NUMBER() OVER (ORDER BY Reput DESC, Name) AS row_number

答案 1 :(得分:0)

如果没有示例数据和输入,这真的很难回答,但是我认为是因为这两个查询执行不同的操作。

第一个查询将对结果进行分页,而分页则强加了顺序-首次加载页面时,$ charlistpagemin和$ charlistpagemax大概为0和10,因此得到前十个结果。

第二个查询没有排序-它只是结果列表(未定义顺序)。 如果您添加

order by Res.row_number desc

在查询末尾,它应该可以工作。