Member 14708983 Ответов: 3

Как получить конкретные данные из таблицы


Всем Привет,
Я использую Microsoft SQL Server 2014.
Мне нужны данные, скажем, только для сектора 7, то есть "Test7", но я получаю данные и для "Test6".

создать таблицу test_data1(имя varchar(100),сектор varchar(100))

вставить в test_data1 значения('Test1','22,23,24')
вставить в test_data1 значения('Test2','2')
вставить в test_data1 значения('Test3','2')
вставить в test_data1 значения('Test4','2,3,4,9')
вставить в test_data1 значения('Test5','26')
вставить в test_data1 значения('Test6','13,14,27')
вставить в test_data1 значения('Test7','5,6,7')

Что я уже пробовал:

выберите * из test_data1
Name	sector
Test1	22,23,24
Test2	2
Test3	2
Test4	2,3,4,9
Test5	26
Test6	13,14,27
Test7	5,6,7


выберите * из test_data1, где сектор типа "%7" или сектор типа"%, 7" или сектор типа " 7,%" или сектор типа"%, 7,%"
Name	sector
Test6	13,14,27
Test7	5,6,7


Хотя этот запрос работает правильно для сектора 2 и сектора 22, где все данные, относящиеся к секторам 2 и 22, отображаются правильно.


выберите * из test_data1, где сектор типа "%2" или сектор типа"%, 2" или сектор типа " 2,%" или сектор типа"%, 2,%"
Name	sector
Test2	2
Test3	2
Test4	2,3,4,9


выберите * из test_data1, где сектор типа "%22" или сектор типа"%, 22" или сектор типа " 22,%" или сектор типа"%, 22,%"
Name	sector
Test1	22,23,24


Может ли кто-нибудь помочь мне получить данные только для сектора 7, то есть данные следующим образом?
Name	sector
Test7	5,6,7

3 Ответов

Рейтинг:
4

Eek Ten Bears

Я полностью согласен с OriginalGriff

У вас может быть причина для построения ваших данных в этой форме, но действительно ли они действительны? Если это так, то у вас есть мириады "выходов" и два выпрыгивают на меня.

1. прочтите на PATINDEX приведенный ниже код найдет единичные экземпляры 7 в любом месте вашей строки, он не найдет 77, 17, 73 или что-то еще.

select * from #test_data1 where PATINDEX('%[^0123456789]7[^0123456789]%', sector) + PATINDEX('%[^0123456789]7', sector) + PATINDEX('7[^0123456789]%', sector)> 0


Это неуклюже, и он будет пропускать, например, вы ставите 07 вместо 7 или 7.0 или, возможно, 100 других вещей. Это также не повторяется.

2. Создайте функцию split string, такую как эта моя, я обычно использую ее при обработке текста, поступающего из импортированных данных, поэтому я могу разделить его на две таблицы в соответствии с мудростью OriginalGriff, но вы можете использовать ее для своего приложения. Опять же, это зависит от того, что ваши строки довольно хорошо себя ведут, но это означает, что вы получаете хорошую таблицу, подобную сущности, чтобы играть с ней в качестве вывода, она также добавляет номера строк для сортировки, что помогает. ПРИМЕЧАНИЕ ЭТО НЕ ИДЕАЛЬНО МНЕ ЭТО НЕ НУЖНО ТАК ЧТО ИСПОЛЬЗУЙТЕ С ОСТОРОЖНОСТЬЮ

ALTER FUNCTION [yourSchema].[SplitString_RowNumbered] (
      @InputString                  nVARCHAR(4000),
      @Delimiter                    VARCHAR(50)
)

RETURNS @Strings TABLE (
      StringRow                             int,
      StringElement                         nVARCHAR(4000)
)
-- adjustment 14/05/2019  delimiters of more than 1 character included the delimiter characters beyond the first character
AS
BEGIN
      IF @Delimiter = ' '
      BEGIN
            SET @Delimiter = ','
            SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
      END

      IF (@Delimiter IS NULL OR @Delimiter = '')
            SET @Delimiter = ','


      DECLARE @Element        nVARCHAR(4000);
      DECLARE @Elements       nVARCHAR(4000);
      DECLARE @DelimIndex     INT;
      DECLARE @RowNumber      INT = 0;

      SET @Elements = @InputString
      SET @DelimIndex = CHARINDEX(@Delimiter, @Elements, 0)
      WHILE (@DelimIndex != 0)
      BEGIN
            SET @Element = SUBSTRING(@Elements, 0, @DelimIndex);  -- get the first element
            SET @RowNumber += 1;                                  -- increment the row
            INSERT INTO @Strings VALUES (@RowNumber, @Element)

            -- Set @ItemList = @ItemList minus one less item
            SET @Elements = SUBSTRING(@Elements, @DelimIndex+len(@Delimiter + 'x') - 1, LEN(@Elements)-@DelimIndex)
            SET @DelimIndex = CHARINDEX(@Delimiter, @Elements, 0)
      END -- End WHILE

      -- have one segment left
      INSERT INTO @Strings VALUES (@RowNumber + 1, @Elements) -- if no deliminators were found @Elements is the @InputString otherwise its the rightnost segment



      RETURN

END -- End Function


Member 14708983

Спасибо за быстрый ответ. Здесь также я получаю правильное решение, используя Ваш запрос для данных сектора 7, но когда я использую тот же запрос для получения сектора 2, он отображает только 1 запись. Я ожидаю 3 записи, как показано в моем первоначальном посте.

выберите * от test_data1 где функция patindex('%[^0123456789]7[^0123456789]%', сектор) + функция patindex('%[^0123456789]7', сектор) + функция patindex('7[^0123456789]%', сектора) и gt; 0

Название сектора
Тест7 5,6,7

выберите * от test_data1 где функция patindex('%[^0123456789]2[^0123456789]%', сектор) + функция patindex('%[^0123456789]2', сектор) + функция patindex('2[^0123456789]%', сектора) и gt; 0

Название сектора
Тест4 2,3,4,9

Eek Ten Bears

Да, мой плохой, я забыл тривиальный случай - либо добавить "и сектор = 2", либо сделать это, что красивее, но включает в себя бессмысленное применение PATINDEX
где функция patindex('%[^0123456789]2[^0123456789]%', сектор) + функция patindex('%[^0123456789]2', сектор) + функция patindex('2[^0123456789]%', сектор) + функция patindex('2', сектор) и gt; 0

Member 14708983

Большое спасибо, дорогая.
Решение PATINDEX сработало. Я проверил данные для различных входных данных, и все, кажется, работает совершенно нормально.

выберите * из test_data1

Название сектора
Тест1 22,23,24
Тест2 2
Тест3 2
Тест4 2,3,4,9
Тест5 26
Тест6 13,14,27
Тест7 5,6,7
Тест8 2,14,15
Тест9 3,14,5
Тест10 8,9
Тест11 2,14
Тест12 12,14

выберите * от test_data1 где функция patindex('%[^0123456789]2[^0123456789]%', сектор) + функция patindex('%[^0123456789]2', сектор) + функция patindex('2[^0123456789]%', сектор) + функция patindex('2', сектор) и gt; 0

Название сектора
Тест2 2
Тест3 2
Тест4 2,3,4,9
Тест8 2,14,15
Тест11 2,14

выберите * от test_data1 где функция patindex('%[^0123456789]26[^0123456789]%', сектор) + функция patindex('%[^0123456789]26', сектор) + функция patindex('26[^0123456789]%', сектор) + функция patindex('26', сектор) и gt; 0

Название сектора
Тест5 26

выберите * от test_data1 где функция patindex('%[^0123456789]8[^0123456789]%', сектор) + функция patindex('%[^0123456789]8', сектор) + функция patindex('8[^0123456789]%', сектор) + функция patindex('8', сектор) и gt; 0

Название сектора
Тест10 8,9

Рейтинг:
0

OriginalGriff

Для начала, не храните ваши данные таким образом. Использование данных, разделенных запятыми внутри столбца, - это Пита для всей обработки, независимо от того, насколько хорошей может показаться идея ti, когда вы начали. Да, его легко вставить, но после этого он становится полным кошмаром, поскольку SQL имеет очень ограниченные возможности обработки строк.

Чтобы проверить, что у вас есть хорошая идея, подумайте о простом изменении: измените Text4, чтобы заменить сектор 4 на сектор 5. Легко ли это сделать?

Вместо этого используйте две таблицы:
TestDatas

ID      INT, IDENTITY (Or UNIQUEIDENTIFIER, your preference
Name    NVARCHAR

Сектора
ID      INT, IDENTITY
Sector  INT
TDID    INT, FOREIGN KEY to TextDatas (Or UNIQUEIDENTIFIER, FOREIGN KEY to TextDatas)
Затем вы можете использовать простое соединение для объединения таблиц, а операции удаления, обновления и выбора становятся относительно тривиальными.


Member 14708983

Спасибо за быстрый ответ. Но входные данные в поле сектора будут разделены только запятыми, например 2,3,4,9 или 1,4,7,22,26

OriginalGriff

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

Member 14708983

Большое спасибо за вашу любезную помощь. Это определенно хорошая идея. Еще раз спасибо.

OriginalGriff

Всегда пожалуйста!

Рейтинг:
0

CHill60

Решение 1-это правильный подход, однако, чтобы вы могли видеть, что вы сделали неправильно, попробуйте заменить его

select * from test_data1 where sector like '%7' or sector like '%,7' or sector like '7,%' or sector like '%,7,%'
с
select * from #test_data1 where sector like '%,7' or sector like '7,%' or sector like '%,7,%'
По сути, вам нужно проверить, что "7" - это последняя часть текста столбца, первая часть текста столбца или где-то посередине-вот почему там есть запятые.

Проверяя '%7', вы дважды проверяли текст столбца, заканчивающийся на "7" - какой-нибудь число, заканчивающееся на 7


Member 14708983

Спасибо за быстрый ответ. После использования запроса, предоставленного вами, я получаю правильные данные для сектора 7, но если я использую тот же запрос для сектора 2, он отображает только 1 запись, в идеале он должен показывать 3 записи.

выберите * из test_data1, где сектор типа"%, 2" или сектор типа " 2,%" или сектор типа"%, 2,%"

Название сектора
Тест4 2,3,4,9

--мой запрос
выберите * из test_data1, где сектор типа "%2" или сектор типа"%, 2" или сектор типа " 2,%" или сектор типа"%, 2,%"

Название сектора
Тест2 2
Тест3 2
Тест4 2,3,4,9

CHill60

Согласно @Eek-Ten-Bears в решении 3 - я также пропустил тривиальный случай

or sector = 2
Однако я не предлагал решения как такового - решение 1-это правильный путь вперед, а решение 3 предлагает способ разбиения данных на необходимые таблицы.

Я только пытался указать, почему ваш запрос не сработал - однако я вижу, что вы все еще включаете where sector like '%2' а это неправильно!

Member 14708983

Большое спасибо за вашу любезную помощь. Я исправил это...