#sql #sql-server #tsql #sql-server-2000
#sql #sql-сервер #tsql #sql-server-2000
Вопрос:
Предисловие: Я осмотрел все stackoverflow.com и погуглите для этого. Я нашел сотни возможных ответов, но либо это неправильная версия SQL Server, либо она вообще не предназначена для SQL Server, и я не настолько искусен, чтобы адаптировать запрос к TSQL для SQL Server 2000. Большинство примеров предполагают, что я хотел бы выполнить какое-то агрегирование, чего мне не нужно делать. Кроме того, многие примеры предполагают фиксированное количество строк (в годовых кварталах, переносящихся на 4 столбца или в аренду, известное число. У меня будет разное количество столбцов в строке.
У меня есть таблица в SQL Server 2000, в которой хранятся слова. Это выглядит так:
MAPENTRY_ID int NOT NULL
PARENT_ID int NOT NULL
ENCODED varchar(10) NOT NULL
MAPENTRY_ID — это первичный ключ. PARENT_ID хранит MAPENTRY_ID «родительского» слова. Это список слов, и поскольку эти слова чувствительны к регистру, для данного «родителя» может быть более одного «дочернего» слова. Если существует только одно слово / регистр (пример ниже — «ABC», тогда MAPENTRY_ID будет равен PARENT_ID.
Некоторые примеры данных выглядят так:
MAPENTRY_ID PARENT_ID ENCODED
----------- --------- -------
8274302 8274302 abaco
8274306 8274302 Abaco
8274308 8274302 ABACO
5217985 5217985 abbynormal
5217987 5217985 Abbynormal
5217986 5217985 AbbyNormal
5217990 5217985 ABBYNORMAL
9285 9285 ABC
1144839 1144839 abc123
1144864 1144839 ABC123
5129019 5129019 abcapp
5129020 5129019 AbcApp
5129021 5129019 ABCAPP
8329759 8329759 abdominals
8329757 8329759 Abdominals
8329761 8329759 ABDOMINALS
8278875 8278875 abmill
8278878 8278875 abMill
8278879 8278875 abMILL
8278876 8278875 Abmill
8278877 8278875 AbMill
8278880 8278875 ABMILL
5217983 5217983 abnormal
5217993 5217983 Abnormal
5217994 5217983 ABNORMAL
8199838 8199838 aboutcopd
8199839 8199838 Aboutcopd
8199841 8199838 AboutCopd
8199840 8199838 AboutCOPD
8199845 8199838 ABOUTCOPD
8199733 8199733 aboutpad
8199756 8199733 Aboutpad
8199744 8199733 AboutPad
8199735 8199733 AboutPAD
8199765 8199733 ABOUTPAD
8199767 8199767 aboutrls
8199768 8199767 Aboutrls
8199770 8199767 AboutRls
8199772 8199767 AboutRLS
8199789 8199767 ABOUTRLS
8672422 8672422 abroad
8672423 8672422 Abroad
8672424 8672422 ABROAD
8478426 8478426 absecon
8478525 8478426 Absecon
8478582 8478426 ABSECON
8427765 8427765 absinthe
8427767 8427765 ABSINTHE
8690704 8690704 absolutely
8690705 8690704 Absolutely
8690706 8690704 ABSOLUTELY
Прочитав много материала, я попробовал следующий SQL:
SELECT MAPENTRY_ID, PARENT_ID, ENCODED
FROM XCO_MASTER
ORDER BY ENCODED, MAPENTRY_ID, PARENT_ID
То, что он произвел, было логически правильным, но больше похоже на древовидную структуру. Это действительно не похоже на что-то большее, чем хорошая «сортировка»… Небольшой пример:
MAPENTRY_ID PARENT_ID ENCODED
----------- --------- -------
8274302 8274302 abaco
8274306 8274302 Abaco
8274308 8274302 ABACO
5217985 5217985 abbynormal
5217987 5217985 Abbynormal
5217986 5217985 AbbyNormal
5217990 5217985 ABBYNORMAL
9285 9285 ABC
1144839 1144839 abc123
1144864 1144839 ABC123
Что мне нужно увидеть, так это результат, подобный:
MAPENTRY_ID ENCODED ENCODED ENCODED ENCODED
----------- ---------- ---------- ---------- ----------
8274302 abaco Abaco ABACO
5217985 abbynormal Abbynormal AbbyNormal ABBYNORMAL
9285 ABC
1144839 abc123 ABC123
И причина, по которой я хотел бы, чтобы это было в таком порядке, заключается в том, что я захочу отобразить эту информацию в виде таблицы HTML на веб-сайте. Я не буду отображать всю таблицу целиком, только результаты запроса по ключевому слову, которые пользователь сможет искать.
Есть ли какой-либо способ сделать это в SQL Server 2000 с использованием TSQL? Я бы предпочел не анализировать результаты моего запроса выше на клиенте, чтобы получить желаемые результаты, если это можно сделать с помощью определенного типа запроса.
Комментарии:
1. @JohnHartsock Он указывает SQL Server 2000 во введении, выделенном курсивом, а также в последнем абзаце.
2. SQL Server 2000.. Сложно, много недоступных интересных вещей: нет cte, нет функций ранжирования, нет PIVOT…
3. Если вы пытаетесь вернуть альтернативные варианты для ключевого слова пользователя, не могли бы вы просто получить всех потомков или родителей из того, что ввел пользователь? Возвращайте их как отдельные строки и используйте их на своей странице? Или вам действительно нужно вернуть всю структуру в этом запросе? Я считаю, что SQL, возвращающий переменное количество столбцов, обычно не является хорошим SQL. Поворот на уровне представления.
4. Что сказал @Adrian. Возможно, вам лучше всего выполнить сводку вне базы данных, то есть в любом коде, генерирующем HTML-таблицу.
5. Не помещайте логику отображения в свою базу данных. Получите свои результаты из базы данных и отформатируйте их в коде приложения.
Ответ №1:
Как указывали некоторые комментарии, я думаю, что делать это снаружи было бы лучше.
Тем не менее в TSQL вы могли бы сделать что-то вроде этого:
DECLARE @i int
SET @i = 1
DECLARE @sql_alter nvarchar(4000)
, @sql_update nvarchar(4000)
, @sql_select nvarchar(4000)
CREATE TABLE #FLAT_TABLE (FID_0 int, FENCODED_0 varchar(10))
SET @sql_select = N'SELECT FID_0, FENCODED_0'
INSERT INTO #FLAT_TABLE (FID_0, FENCODED_0)
SELECT MAPENTRY_ID
, ENCODED
FROM XCO_MASTER
WHERE MAPENTRY_ID = PARENT_ID
while (@@ROWCOUNT > 0) begin
SET @sql_select = @sql_select ', FID_' @i
SET @sql_alter = N'
ALTER TABLE #FLAT_TABLE ADD COLUMN FID_' @i N' int
ALTER TABLE #FLAT_TABLE ADD COLUMN FENCODED_' @i N' varchar(10)
'
SET @sql_update = N'
UPDATE #FLAT_TABLE
SET FID_' @i N' = MAPENTRY_ID
, FENCODED_' @i N' = ENCODED
FROM XCO_MASTER
WHERE MAPENTRY_ID <> PARENT_ID
and MAPENTRY_ID = FID_' (Cast (@i - 1) as nvarchar(8))
'
SET @i = @i 1
sp_executesql @sql_alter
sp_executesql @sql_update
end
@sql_select = @sql_select ' FROM #FLAT_TABLE'
SELECT @sql_select
Это всего лишь идея, вам нужно будет внести некоторые исправления (например, cast @i).
Предупреждение
Будьте осторожны с @@ROWCOUNT > 0
условием, это может привести к бесконечному циклу, если вы допустите ошибку. Вы можете поместить что-то вроде @@ROWCOUNT > 0 and @i < @MAX_COLUMNS
, чтобы избежать каких-либо проблем.
Комментарии:
1. Глоток. 🙂 Спасибо, и я буду смотреть на это сейчас и перепечатывать то, что я узнаю.
2. Я внес некоторые исправления и заставил его проанализировать и, наконец, запустить! Очень интересно. Он добавляет столбец с именем «FID_1, который ему не нужно делать. Просто MAPENTRY_ID и n-количество ЗАКОДИРОВАННЫХ столбцов. Я попытаюсь изменить это, чтобы сделать это, и опубликую то, что я узнал здесь. Кто знает, может быть, это поможет и другим.
3. Вам нужно
FID_[1-N]
сравнить вUPDATE
. В конце должны быть два столбца (FID_N
иFENCODED_N
), которые вам не нужны. В любом случае будьте очень осторожны,@@ROWCOUNT > 0
потому что, если вы допустите ошибку, у вас может быть бесконечный цикл.