#sql #sql-server
#sql #sql-server
Вопрос:
У меня есть таблица со списком папок, и я хочу вернуть только папки верхнего уровня.
Например, если исходная таблица (tblFolders) содержит один столбец (Fldrs), как показано ниже:
Fldrs
C:Folder1
C:Folder1Subfolder1
C:Folder1Subfolder2
C:Folder2Subfolder1
Я хотел бы вернуть:
C:Folder1
C:Folder2Subfolder1
Заранее спасибо
Комментарии:
1. Какая у вас СУБД? Разные движки имеют разные возможности обработки строк
2. Если вы добавите
C:Folder2Subfolder2
к образцу данные, изменится ли желаемый результат?3. Хороший вопрос, ярлх. В этом случае я бы хотел, чтобы ответ включал оба C:Folder2Subfolder1 и C:Folder2Subfolder2 . Для папок верхнего уровня могут учитываться только папки, находящиеся в данный момент в таблице.
4. Моей СУБД является Microsoft SQL server
5. Хорошо, я пометил ваш запрос соответствующим
sql-server
образом.
Ответ №1:
Вы хотите выбрать все папки, для которых не существует родительской папки. Следовательно, наиболее читаемый запрос должен NOT EXISTS
содержать предложение.
select *
from tblfolders f
where not exists
(
select null
from tblfolders p
where f.fldr like p.fldr '_%'
);
В LIKE
шаблоне символ _
представляет один символ, символ %
представляет ноль или более символов. _%
следовательно, один или несколько символов. Таким образом, мы удостоверяемся, что путь к дочерней папке длиннее, чем путь к родительской папке.
Комментарии:
1. Большое спасибо, Торстен. Ваш отзыв был очень полезным и информативным. При сравнении результатов ваш ответ действительно дает ожидаемые результаты, и мой опубликованный ответ имеет отмеченный вами недостаток (возвращает только верхние папки с дочерними папками), а также возвращает нежелательные папки 2-го уровня, если существуют папки 3-го уровня. Еще раз спасибо.
Ответ №2:
Я понял это, и я публикую ответ, который я нашел. Не стесняйтесь комментировать потенциальные улучшения.
select distinct F2.fldr as TopLevelFolders
from tblFolders F1
join tblFolders F2 on F1.fldr like F2.fldr '%'
where F1.fldr <> F2.fldr
order by F2.fldr
Комментарии:
1. Хорошо, что вы приложили к этому некоторые усилия и самостоятельно нашли решение. Однако ваш запрос возвращает только верхние папки, у которых есть дочерние папки. Вы можете легко протестировать dbfiddle.uk : dbfiddle.uk /…
2. За исключением связующих таблиц, которые нам нужны для реализации отношений m: n, мое эмпирическое правило таково: объединяйте только те таблицы, данные которых я хочу иметь в своих результатах. Ограничения, с другой стороны, относятся к
WHERE
предложению. Для поиска я использую[NOT] IN
для простых вещей и[NOT] EXISTS
для более сложных условий. (Иногда поиск может быть выполнен даже с<
помощью ,>
,<>
, и=
. Напримерwhere order_date = (select max(order_date) from ...)
, Не присоединяться, когда в этом нет необходимости.DISTINCT
это типичный показатель того, что вы объединили слишком много данных.