使用rowid在sqlite中的公用表表达式

时间:2015-03-20 04:48:17

标签: sqlite common-table-expression nested-sets adjacency-list

我在http://dataeducation.com/the-hidden-costs-of-insert-exec/

找到了一篇关于将邻接转换为嵌套集的好文章

使用的SQL语言是Microsoft SQL Server(我认为),我正在尝试将文章中给出的示例转换为sqlite(因为这是我在Macbook上可以轻松访问的内容)。

我似乎遇到的问题是将整个CTE查询的部分转换为使用Employee Rows

EmployeeRows AS
(
    SELECT
         EmployeeLevels.*,
         ROW_NUMBER() OVER (ORDER BY thePath) AS Row
    FROM EmployeeLevels
)

我将此转换为

EmployeeRows AS
(
    SELECT
         EmployeeLevels.*,
         rowid AS Row
    FROM EmployeeLevels
    ORDER BY thePath
)

并运行CTE查询(没有语法错误),但我得到的输出是一个没有填充Row和Lft和Rgt列的表

ProductName  ProductID   ParentProductID  TreePath    HLevel      Row         Lft         Rgt       
-----------  ----------  ---------------  ----------  ----------  ----------  ----------  ----------
Baby Goods   0                            0           1                                             
Baby Food    10          0                0.10        2                                             
All Ages Ba  100         10               0.10.100    3                                             
Strawberry   200         100              0.10.100.2  4                                             
Baby Cereal  250         100              0.10.100.2  4                                             
Beginners    150         10               0.10.150    3                                             
Formula Mil  300         150              0.10.150.3  4                                             
Heinz Formu  310         300              0.10.150.3  5                                             
Nappies      20          0                0.20        2                                             
Small Pack   400         20               0.20.400    3                                             
Bulk Pack N  450         20               0.20.450    3                                             

我认为问题的开始是Row没有填充,因此Lft和Rgt列不会被查询的以下部分填充。

那里有没有sqlite专家告诉我:

  • 我正在正确翻译查询的rowid部分
  • sqlite支持CTE查询的一部分中的rowid
  • 有更好的方法吗? :)

任何帮助表示赞赏:)

1 个答案:

答案 0 :(得分:0)

我可以正确翻译查询的rowid部分

否。

SQL:

SELECT
     EmployeeLevels.*,
     rowid AS Row
FROM EmployeeLevels
ORDER BY thePath

在SQLite中将Row定义为表EmployeeLevels的行ID,而忽略了order子句。这与ROW_NUMBER() OVER (ORDER BY thePath) AS Row

的意图不同

sqlite在CTE查询的一部分中是否支持rowid

不幸的是,没有。我想你的意思是这样:

WITH foo AS (
   SELECT * FROM bar ORDER BY col_a
)
SELECT rowid, *
FROM foo

但是SQLite将不会在rowid中报告foo的此类列。

还有更好的方法吗?

不确定它会更好,但至少它能起作用。在SQLite中,您有一种临时表机制,只要您打开连接并且没有故意删除它,该表就存在。在我的示例中重写上述SQL:

CREATE TEMP TABLE foo AS 
SELECT * FROM bar ORDER BY col_a
;
SELECT rowid, *
FROM foo
;
DROP TABLE foo
;

这将在没有SQLite抱怨的情况下运行。

更新

从SQLite 3.25.0版本开始,支持窗口功能。因此,如果您碰巧使用更新的SQLite,则可以在CTE中使用row_number() over (order by x)表达式