Как написать sql в SQLite с этим?

#sql #sqlite #sql-update #common-table-expression

#sql #sqlite #sql-обновление #common-table-expression

Вопрос:

     WITH cteCountDownlines AS
( --=== Count each occurrence of EmployeeID in the sort path
 SELECT EmployeeID = CAST(SUBSTRING(h.SortPath,t.N,4) AS INT), 
        NodeCount  = COUNT(*) --Includes current node
   FROM dbo.Hierarchy h, 
        dbo.HTally t
  WHERE t.N BETWEEN 1 AND DATALENGTH(SortPath)
  GROUP BY SUBSTRING(h.SortPath,t.N,4)
) --=== Update the NodeCount and calculate the RightBower
 UPDATE h
    SET h.NodeCount  = downline.NodeCount,
        h.RightBower = (downline.NodeCount - 1) * 2   LeftBower   1
   FROM dbo.Hierarchy h
   JOIN cteCountDownlines downline
     ON h.EmployeeID = downline.EmployeeID
;
 

это из https://www.sqlservercentral.com/articles/hierarchies-on-steroids-1-convert-an-adjacency-list-to-nested-sets.
Я пробовал много способов, но не работает.
Разделенные cteCountDownlines и join работают просто отлично, но не знаю, как их объединить

Комментарии:

1. Какова ваша версия SQLite?

2. Как именно это не работает — выглядит нормально.

3. @forpas Я пытался использовать join в SQLite, и ни один из них не работает .. И я хорошо справляюсь с версией без JOIN вообще.

Ответ №1:

Если вы используете SQLite 3.33.0 , вы можете использовать UPDATE...FROM синтаксис:

 WITH cteCountDownlines AS (
 SELECT CAST(SUBSTR(h.SortPath,t.N,4) AS INT) EmployeeID, 
        COUNT(*) NodeCount
  FROM Hierarchy h INNER JOIN HTally t
  ON t.N BETWEEN 1 AND LENGTH(h.SortPath)
  GROUP BY SUBSTR(h.SortPath,t.N,4)
)
UPDATE Hierarchy AS h
SET NodeCount  = downline.NodeCount,
    RightBower = (downline.NodeCount - 1) * 2   h.LeftBower   1
FROM cteCountDownlines downline
WHERE h.EmployeeID = downline.EmployeeID;
 

Для SQLite 3.15.0 вы можете использовать этот синтаксис:

 WITH cteCountDownlines AS (
 SELECT CAST(SUBSTR(h.SortPath,t.N,4) AS INT) EmployeeID, 
        COUNT(*) NodeCount
  FROM Hierarchy h INNER JOIN HTally t
  ON t.N BETWEEN 1 AND LENGTH(h.SortPath)
  GROUP BY SUBSTR(h.SortPath,t.N,4)
)
UPDATE Hierarchy AS h
SET (NodeCount, RightBower) = (
  SELECT downline.NodeCount,
         (downline.NodeCount - 1) * 2   h.LeftBower   1
  FROM cteCountDownlines downline
  WHERE h.EmployeeID = downline.EmployeeID
);
 

Обратите внимание, что нет эквивалента DATALENGTH() функции SQL Server.
Функция LENGTH() Я использовал возвращает количество символов в строке.

Комментарии:

1. Большое вам спасибо! Между тем, я попытался закончить свою версию, которая, похоже, работает и точно похожа yours…codepad.org/OXTMDKg7 (у моей таблицы другое имя) и я в замешательстве, почему в его версии использовалось СОЕДИНЕНИЕ? Кажется, операция объединения вообще отсутствует.

2. @T.Worm На странице ссылки в вашем вопросе используется синтаксис SQL Server, который не поддерживается SQLite. СИНТАКСИС ОБНОВЛЕНИЯ SQLite похож на Postgres.

3. Извините, это может быть не по теме. Я использовал это codepad.org/P5E6jLcT вместо чего-то вроде ПРИВЕДЕНИЯ (якорь. Идентификатор сотрудника КАК ДВОИЧНЫЙ (4)) . Мне интересно, приведет ли это к повышению производительности или нет?

4. В SQLite нет ДВОИЧНОГО типа данных. Прочитайте это: sqlite.org/datatype3.html Что касается остальной части кода, единственное, что я могу сказать на первый взгляд, это то, что рекурсивный запрос (в зависимости от глубины рекурсии) может плохо сказаться на производительности.