Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите решить задачку!  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Всем привет!
Передо мной встала достаточно нетривиальная задачка. Как её решить - никак не могу сообразить.
Имеется filetable (если кто-то не знаком, пример ниже). Нужно для каждой папки, в которой содержатся файлы, выбрать 2 поля у каждого файла, и добавить значения этих полей в новые столбцы, для ОДНОЙ записи, соответствующей этой папке.
Например:

Имеется таблица:
uid name path parentpath
uid1 folder folderPath ...
uid2 file1 file1Path folderPath
uid3 file2 file2Path folderPath
uid4 file1 file1Path folderPath
... ... ... ...


Для всех этих файлов должна получиться одна строка:

uid name Name1 Path1 Name2 Path2 Name3 Path3 ...
uid1 folder file1 file1Path file2 file2Path file3 file3Path ...


В общем случае, для всей таблицы типа:

uid name path parentpath
uid1 folder1 folder1Path ...
uid2 file1 file1Path folder1Path
uid3 file2 file2Path folder1Path
uid4 file1 file1Path folder1Path
uid5 folder2 folder2Path ...
uid6 file4 file4Path folder2Path
uid7 folder3 folder3Path ...
uid8 file5 file5Path folder3Path
uid9 file6 file6Path folder3Path
... ... ... ...


Должно получиться нечто следующее:

uid name Name1 Path1 Name2 Path2 Name3 Path3 ...
uid1 folder1 file1 file1Path file2 file2Path file3 file3Path ...
uid5 folder2 file4 file4Path null null null null ...
uid7 folder3 file5 file5Path file6 file6Path null null ...


Причем, желательно, чтобы эти результирующие столбцы создавались автоматически, в зависимости от самого большого количества файлов в одном каталоге.
13 июл 17, 11:24    [20639947]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
holod-iinna
Member

Откуда:
Сообщений: 96
fgarfield,

почитайте про PIVOT.
Делал похожий костыль для отчета, динамически считывая все столбцы.
Но кода не осталось...
13 июл 17, 12:07    [20640163]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
fgarfield
Всем привет!
Передо мной встала достаточно нетривиальнаяизвращенная задачка

И позвольте поинтересоваться, кто вам задачу поставил?
Если руководство, сочувствую, если сами себе - порицаю.
13 июл 17, 12:23    [20640220]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
fgarfield
Member

Откуда:
Сообщений: 20
holod-iinna,
спасибо за ответ! PIVOT/UNPIVOT были моими первыми идеями. Но если использовать их, то я не понимаю в какую конструкцию их вставить, чтобы они работали с определенными наборами строк? цикл, курсор, или в какой-то запрос? нужно ли потом склеивать строки-результаты? если да, то как?
Не могу даже осознать, с чего подступиться к решению (опыт работы в SQL не очень большой)
13 июл 17, 12:25    [20640226]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
Добрый Э - Эх
Guest
fgarfield
Причем, желательно, чтобы эти результирующие столбцы создавались автоматически, в зависимости от самого большого количества файлов в одном каталоге.


fgarfield
holod-iinna,
спасибо за ответ! PIVOT/UNPIVOT были моими первыми идеями. Но если использовать их, то я не понимаю в какую конструкцию их вставить, чтобы они работали с определенными наборами строк? цикл, курсор, или в какой-то запрос? нужно ли потом склеивать строки-результаты? если да, то как?
Не могу даже осознать, с чего подступиться к решению (опыт работы в SQL не очень большой)

динамический SQL + PIVOT.
13 июл 17, 12:27    [20640235]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
fgarfield
holod-iinna,
Не могу даже осознать, с чего подступиться к решению (опыт работы в SQL не очень большой)

Обычно к решению подступаются с поиска в гугле. Читать, пробовать. Приходить с наработками.
Можете не благодарить, мы уже привыкли.
13 июл 17, 12:29    [20640244]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Руслан Дамирович,
Здравствуйте! Задачу я поставил себе сам.
В базе хранятся элементы. Каждому элементу может быть назначен 0, 1, или несколько файлов. Для однотипных элементов набор файлов одинаков. Софт, который вытаскивает каждый элемент из базы, требует данные о соответствующих файлах в том виде, который я описал. Чтобы не создавать в таблице элементов дополнительные столбцы и впоследствии не заполнять их ссылками на файлы, я решил каждому элементу назначать лишь каталог. А затем уже посредством решения упомянутой задачи, получать все содержащиеся в нём файлы.
Мне показалось, что это наиболее рациональный подход.
13 июл 17, 12:32    [20640266]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Руслан Дамирович
fgarfield
holod-iinna,
Не могу даже осознать, с чего подступиться к решению (опыт работы в SQL не очень большой)

Обычно к решению подступаются с поиска в гугле. Читать, пробовать. Приходить с наработками.
Можете не благодарить, мы уже привыкли.


Я привык работать именно по такой схеме. Но я который день ломаю голову, и не могу выдавить из себя ни единой строчки. А обратиться за помощью, кроме как на форум, некуда.
13 июл 17, 12:35    [20640272]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Добрый Э - Эх,
Насколько я смог осмыслить функцию PIVOT, она работает только с агрегатными функциями. Но если мне не нужно (как я понимаю) ничего агрегировать, подойдет ли она ?
13 июл 17, 12:36    [20640284]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
fgarfield
Руслан Дамирович,
Здравствуйте! Задачу я поставил себе сам.
В базе хранятся элементы. Каждому элементу может быть назначен 0, 1, или несколько файлов. Для однотипных элементов набор файлов одинаков. Софт, который вытаскивает каждый элемент из базы, требует данные о соответствующих файлах в том виде, который я описал. Чтобы не создавать в таблице элементов дополнительные столбцы и впоследствии не заполнять их ссылками на файлы, я решил каждому элементу назначать лишь каталог. А затем уже посредством решения упомянутой задачи, получать все содержащиеся в нём файлы.
Мне показалось, что это наиболее рациональный подход.

Меняйте софт, пока не поздно.
Вот пример без динамики. А в вашем случае, нужно будет ОЧЕНЬ много динамики.
+

DECLARE 
  @tbl TABLE ( 
    [uid] VARCHAR(32),
    [name] NVARCHAR(255),
    [path] NVARCHAR(255),
    [parentpath] NVARCHAR(255)
  )
;
INSERT
INTO
  @tbl
VALUES
  ( 'uid1', 'folder1', 'folder1Path', '...' ),
  ( 'uid2', 'file1', 'file1Path', 'folder1Path' ),
  ( 'uid3', 'file2', 'file2Path', 'folder1Path' ),
  ( 'uid4', 'file3', 'file3Path', 'folder1Path' ),
  ( 'uid5', 'folder2', 'folder2Path', '...' ),
  ( 'uid6', 'file4', 'file4Path', 'folder2Path' ),
  ( 'uid7', 'folder3', 'folder3Path', '...' ),
  ( 'uid8', 'file5', 'file5Path', 'folder3Path' ),
  ( 'uid9', 'file6', 'file6Path', 'folder3Path' )
;
WITH
t0 AS (
  SELECT
    t.[uid],
    t.[name],
    [file] = t1.[name],
    [path] = t1.[path],
    [rn] = ROW_NUMBER() OVER ( PARTITION BY t.[uid], t.[name] ORDER BY t1.[uid] )
  FROM
    @tbl t
    LEFT JOIN @tbl t1 ON (
          t1.[parentpath] = t.[path] )
  WHERE
    t.[name] LIKE 'folder%'
),
tn1 AS (
  SELECT
    [uid],
    [name],
    [rn],
    [file]
  FROM
    t0
),
tn2 AS (
  SELECT
    [uid],
    [name],
    [rn],
    [path]
  FROM
    t0
),
pvt1 AS (
  SELECT
    *
  FROM
    tn1
    PIVOT (
      MAX( [file] )
      FOR [rn] IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9] )
    ) pvt
),
pvt2 AS (
  SELECT
    *
  FROM
    tn2
    PIVOT (
      MAX( [path] )
      FOR [rn] IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9] )
    ) pvt
)
SELECT
  pvt1.[uid],
  pvt1.[name],
  [name1] = pvt1.[1],
  [path1] = pvt2.[1],
  [name2] = pvt1.[2],
  [path2] = pvt2.[2],
  [name3] = pvt1.[3],
  [path3] = pvt2.[3],
  [name4] = pvt1.[4],
  [path4] = pvt2.[4],
  [name5] = pvt1.[5],
  [path5] = pvt2.[5],
  [name6] = pvt1.[6],
  [path6] = pvt2.[6],
  [name7] = pvt1.[7],
  [path7] = pvt2.[7],
  [name8] = pvt1.[8],
  [path8] = pvt2.[8],
  [name9] = pvt1.[9],
  [path9] = pvt2.[9]
FROM
  pvt1
  LEFT JOIN pvt2 ON (
        pvt2.[uid] = pvt1.[uid]
    AND pvt2.[name] = pvt2.[name] )

13 июл 17, 12:48    [20640339]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Добрый Э - Эх,
Я правильно пониманию, что динамический запрос - это конкатенация запроса в строку в цикле с помощью переменных?
Если так, то в эту строку надо вставлять блок SELECT для каждого каталога? это ведь получиться очень большая и сложная строка. Это нормально?
13 июл 17, 12:51    [20640353]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
fgarfield,

гугел SQL rows to columns даст массу материала на вкус и цвет
13 июл 17, 12:53    [20640357]     Ответить | Цитировать Сообщить модератору
 Re: Помогите решить задачку!  [new]
dies irae
Member

Откуда:
Сообщений: 78
ну раз задачу сами себе поставили, возможно стоит отказаться от мысли плодить столбцы и пойти дорогой попроще?
например, вернуть в одном поле с разделителем:
DECLARE 
  @tbl TABLE ( 
    [uid] VARCHAR(32),
    [name] NVARCHAR(255),
    [path] NVARCHAR(255),
    [parentpath] NVARCHAR(255)
  )
;
INSERT
INTO
  @tbl
VALUES
  ( 'uid1', 'folder1', 'folder1Path', '...' ),
  ( 'uid2', 'file1', 'file1Path', 'folder1Path' ),
  ( 'uid3', 'file2', 'file2Path', 'folder1Path' ),
  ( 'uid4', 'file3', 'file3Path', 'folder1Path' ),
  ( 'uid5', 'folder2', 'folder2Path', '...' ),
  ( 'uid6', 'file4', 'file4Path', 'folder2Path' ),
  ( 'uid7', 'folder3', 'folder3Path', '...' ),
  ( 'uid8', 'file5', 'file5Path', 'folder3Path' ),
  ( 'uid9', 'file6', 'file6Path', 'folder3Path' )
;


select name
	, (
	select path + ',' as [text()]
	from @tbl as i where i.parentpath = t.path
	for xml path('')
	)
from @tbl as t
where parentpath = '...'
13 июл 17, 15:21    [20641135]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить