SQL Заказ родителем и ребенком - PullRequest
2 голосов
/ 25 марта 2020

В основном мне нужна помощь в моем запросе здесь. Я хочу быть в правильном порядке, потому что ребенок должен быть под именем родителей и в порядке AZ. Но если я добавлю subChild под дочерним элементом (Split 1), порядок будет неправильным. Это должно быть под Room Rose.

p / s: подчиненный ребенок также может создать другого подчиненного ребенка

ЗДЕСЬ Я ОБЕСПЕЧИВАЮ ДЕМО

Благодарим Вас за помощь, чтобы я получил этот заказ правильно?

SELECT A.venueID
     , B.mainVenueID
     , A.venueName 
  FROM tblAdmVenue A 
  LEFT 
  JOIN tblAdmVenueLink B
    ON A.venueID = B.subVenueID
 ORDER   
    BY COALESCE(B.mainVenueID, A.venueID)
     , B.mainVenueID IS NOT NULL
     , A.venueID

enter image description here

Я хочу, чтобы он возвратил заказ примерно так.

venueName
--------------
Banquet
Big Room
-Room Daisy
-Room Rose
  -Split 1
Hall
-Meeting Room WP

Кажется, этот рекурсивный подход также не работает

WITH venue_ctg AS (
  SELECT A.venueID, A.venueName, B.mainVenueID 
  FROM tblAdmVenue A LEFT JOIN tblAdmVenueLink B
  ON A.venueID = B.subVenueID
  WHERE B.mainVenueID IS NULL 

  UNION ALL

  SELECT A.venueID, A.venueName, B.mainVenueID 
  FROM tblAdmVenue A LEFT JOIN tblAdmVenueLink B
  ON A.venueID = B.subVenueID
  WHERE B.mainVenueID IS NOT NULL
)
SELECT *
FROM venue_ctg ORDER BY venueName

выходной дан

enter image description here

Ответы [ 4 ]

1 голос
/ 27 марта 2020

Для ваших данных вы можете использовать это: Чтобы отобразить это правильно, вы можете использовать SEPARATPR как запятую, и разделить возвращенные данные, и проверить иерархию

-- schema
CREATE TABLE tblAdmVenue (
    venueID VARCHAR(225) NOT NULL,
    venueName VARCHAR(225) NOT NULL,
    PRIMARY KEY(venueID)
);

CREATE TABLE tblAdmVenueLink (
    venueLinkID VARCHAR(225) NOT NULL,
    mainVenueID VARCHAR(225) NOT NULL,
    subVenueID VARCHAR(225) NOT NULL,
    PRIMARY KEY(venueLinkID)
    -- FOREIGN KEY (DepartmentId) REFERENCES Departments(Id)
);

-- data
INSERT INTO tblAdmVenue (venueID, venueName)
VALUES ('LA43', 'Big Room'), ('LA44', 'Hall'),
       ('LA45', 'Room Daisy'), ('LA46', 'Room Rose'),
       ('LA47', 'Banquet'), ('LA48', 'Split 1'),
       ('LA49', 'Meeting Room WP');

INSERT INTO tblAdmVenueLink (venueLinkID, mainVenueID, subVenueID)
VALUES ('1', 'LA43', 'LA45'), ('2', 'LA43', 'LA46'),
       ('3', 'LA46', 'LA48'), ('4', 'LA44', 'LA49');
✓

✓

✓

✓
with recursive cte (subVenueID, mainVenueID,level) as (
  select     subVenueID,
             mainVenueID, 1 as level
  from       tblAdmVenueLink
  union
  select     p.subVenueID,
             cte.mainVenueID,
             cte.level+1
  from       tblAdmVenueLink p
  inner join cte
          on p.mainVenueID = cte.subVenueID
)
select 

    CONCAT(GROUP_CONCAT(b.venueName  ORDER BY level DESC SEPARATOR  '-->') ,'-->',a.venueName)
from cte c 
LEFT JOIN tblAdmVenue a ON a.venueID = c.subVenueID 
LEFT JOIN tblAdmVenue b ON b.venueID = c.mainVenueID
GROUP BY subVenueID;
| CONCAT(GROUP_CONCAT(b.venueName  ORDER BY level DESC SEPARATOR  '-->') ,'-->',a.venueName) |
| :----------------------------------------------------------------------------------------- |
| Big Room-->Room Daisy                                                                      |
| Big Room-->Room Rose                                                                       |
| Big Room-->Room Rose-->Split 1                                                             |
| Hall-->Meeting Room WP                                                                     |

дБ <> скрипка здесь

0 голосов
/ 01 апреля 2020

Сначала вы хотите, чтобы ваши данные были упорядочены в алфавитном порядке и глубине.

Распространенным решением для этого является обход структуры от верхнего элемента, конкатенация пути к каждому элементу в виде go. Затем вы можете напрямую использовать путь для упорядочения.

Вот как это сделать в MySQL 8.0 с рекурсивным запросом

with recursive cte(venueID, venueName, mainVenueID, path, depth) as (
    select v.venueID, v.venueName, cast(null as char(100)), venueName, 0
    from tblAdmVenue v
    where not exists (select 1 from tblAdmVenueLink l where l.subVenueID = v.venueID)
    union all
    select v.venueID, v.venueName, c.venueID, concat(c.path, '/', v.venueName), c.depth + 1
    from cte c
    inner join tblAdmVenueLink l on l.mainVenueID = c.venueID
    inner join tblAdmVenue v on v.venueID = l.subVenueID
)
select * from cte order by path

Якорь рекурсивного запроса выбирает верхние узлы ( ie строки, идентификаторы которых не существуют в столбце subVenueID таблицы ссылок). Затем рекурсивная часть следует за отношениями.

В качестве бонуса я добавил столбец level, представляющий глубину каждого узла, начиная с 0 для верхних узлов.

Демонстрация на DB Fiddle :

venueID | venueName       | mainVenueID | path                       | depth
:------ | :-------------- | :---------- | :------------------------- | ----:
LA47    | Banquet         | <em>null</em>        | Banquet                    |     0
LA43    | Big Room        | <em>null</em>        | Big Room                   |     0
LA45    | Room Daisy      | LA43        | Big Room/Room Daisy        |     1
LA46    | Room Rose       | LA43        | Big Room/Room Rose         |     1
LA48    | Split 1         | LA46        | Big Room/Room Rose/Split 1 |     2
LA44    | Hall            | <em>null</em>        | Hall                       |     0
LA49    | Meeting Room WP | LA44        | Hall/Meeting Room WP       |     1
0 голосов
/ 29 марта 2020

Полагаю, у вас есть:

  1. таблица tblAdmVenue A - список мест; и
  2. table tblAdmVenueLink B - это таблица дерева отношений для parent-child

. По вашему вопросу о том, как получить правильный порядок сортировки, я думаю, что одним из приемов является объединение названия родительских мест.

with q0(venueID, venueName, mainVenueID, venuePath) as (
  select
    A.venueID,
    A.venueName,
    null,
    A.venueName
  from tblAdmVenue A
       left join tblAdmVenue B on A.venueID = B.subVenueID
  where B.mainVenueID is null
  union all
  select
    A.venueID,
    A.venueName,
    q0.venueID,
    q0.venuePath + char(9) + A.venueName
  from q0
       inner join tblAdmVenue B on q0.venueID = B.mainVenueID
       inner join tblAdmVenue A on A.venueID = B.subVenueID
)
select venueID, venueName, mainVenueID
from q0
order by venuePath
0 голосов
/ 27 марта 2020

Используйте только одну таблицу, а не две. Первая таблица содержит всю необходимую информацию.

Затем запустите CTE со строками WHERE mainVenueID IS NULL, без JOIN необходимости.

Это может быть хорошим руководством: { ссылка }

Его «лес» близок к тому, что вы хотите.

...