Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Chọn mysql đệ quy?

CREATE DEFINER = 'root'@'localhost'
PROCEDURE test.GetHierarchyUsers(IN StartKey INT)
BEGIN
  -- prepare a hierarchy level variable 
  SET @hierlevel := 00000;

  -- prepare a variable for total rows so we know when no more rows found
  SET @lastRowCount := 0;

  -- pre-drop temp table
  DROP TABLE IF EXISTS MyHierarchy;

  -- now, create it as the first level you want... 
  -- ie: a specific top level of all "no parent" entries
  -- or parameterize the function and ask for a specific "ID".
  -- add extra column as flag for next set of ID's to load into this.
  CREATE TABLE MyHierarchy AS
  SELECT U.ID
       , U.Parent
       , U.`name`
       , 00 AS IDHierLevel
       , 00 AS AlreadyProcessed
  FROM
    Users U
  WHERE
    U.ID = StartKey;

  -- how many rows are we starting with at this tier level
  -- START the cycle, only IF we found rows...
  SET @lastRowCount := FOUND_ROWS();

  -- we need to have a "key" for updates to be applied against, 
  -- otherwise our UPDATE statement will nag about an unsafe update command
  CREATE INDEX MyHier_Idx1 ON MyHierarchy (IDHierLevel);


  -- NOW, keep cycling through until we get no more records
  WHILE @lastRowCount > 0
  DO

    UPDATE MyHierarchy
    SET
      AlreadyProcessed = 1
    WHERE
      IDHierLevel = @hierLevel;

    -- NOW, load in all entries found from full-set NOT already processed
    INSERT INTO MyHierarchy
    SELECT DISTINCT U.ID
                  , U.Parent
                  , U.`name`
                  , @hierLevel + 1 AS IDHierLevel
                  , 0 AS AlreadyProcessed
    FROM
      MyHierarchy mh
    JOIN Users U
    ON mh.Parent = U.ID
    WHERE
      mh.IDHierLevel = @hierLevel;

    -- preserve latest count of records accounted for from above query
    -- now, how many acrual rows DID we insert from the select query
    SET @lastRowCount := ROW_COUNT();


    -- only mark the LOWER level we just joined against as processed,
    -- and NOT the new records we just inserted
    UPDATE MyHierarchy
    SET
      AlreadyProcessed = 1
    WHERE
      IDHierLevel = @hierLevel;

    -- now, update the hierarchy level
    SET @hierLevel := @hierLevel + 1;

  END WHILE;


  -- return the final set now
  SELECT *
  FROM
    MyHierarchy;

-- and we can clean-up after the query of data has been selected / returned.
--    drop table if exists MyHierarchy;


END

Nó có vẻ cồng kềnh, nhưng để sử dụng nó, hãy làm

call GetHierarchyUsers( 5 );

(hoặc bất kỳ ID khóa nào bạn muốn LÊN cây phân cấp).

Tiền đề là bắt đầu với một KEY bạn đang làm việc. Sau đó, sử dụng điều đó làm cơ sở để tham gia vào bảng người dùng LẠI, nhưng dựa trên ID PHỤ HUYNH của mục nhập đầu tiên. Sau khi tìm thấy, hãy cập nhật bảng tạm thời để không thử và tham gia lại cho khóa đó vào chu kỳ tiếp theo. Sau đó, tiếp tục cho đến khi không tìm thấy khóa ID "mẹ" nào nữa.

Điều này sẽ trả lại toàn bộ hệ thống phân cấp của các bản ghi cho đến cha mẹ bất kể việc lồng sâu đến mức nào. Tuy nhiên, nếu bạn chỉ muốn cha mẹ CUỐI CÙNG, bạn có thể sử dụng biến @hierlevel để chỉ trả về biến mới nhất trong tệp đã thêm hoặc ORDER BY và LIMIT 1



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. pyodbc + MySQL + Windows:Không tìm thấy tên nguồn dữ liệu và không có trình điều khiển mặc định nào được chỉ định

  2. Có bất lợi nào khi sử dụng varchar chung (255) cho tất cả các trường dựa trên văn bản không?

  3. Làm cách nào để đặt 'mệnh đề if' trong một chuỗi SQL?

  4. PHP PDO và MySQLi

  5. MySQL:Bạn không thể chỉ định 'nhiệm vụ' của bảng mục tiêu để cập nhật trong mệnh đề FROM