SQL-запрос с несколькими значениями в одном столбце - PullRequest
5 голосов
/ 10 мая 2010

Я бился головой о стол, пытаясь понять это. У меня есть таблица, в которой хранится информация о работе и причины, по которым работа не была завершена. Причины числовые, 01,02,03 и т. Д. У вас может быть две причины для ожидающей работы. Если вы выберете две причины, они будут храниться в одном столбце через запятую. Это пример из таблицы JOBID :

Job_Number     User_Assigned     PendingInfo

1              user1             01,02

Существует еще одна таблица с именем Pending , в которой хранится то, что на самом деле представляют эти значения. 01 = Недостаточно информации, 02 = Недостаточно времени, 03 = Ожидание просмотра. Пример:

Pending_Num    PendingWord

01             Not Enough Info
02             Not Enough Time

То, что я пытаюсь сделать, - это запросить базу данных, чтобы получить все номера вакансий, пользователей, ожидающую информацию и причину ожидания. Я могу выделить первое значение, но не могу понять, как сделать второе. Что мои ограниченные навыки имеют до сих пор:

select Job_number,user_assigned,SUBSTRING(pendinginfo,0,3),pendingword
from jobid,pending
where
    SUBSTRING(pendinginfo,0,3)=pending.pending_num and
    pendinginfo!='00,00' and
    pendinginfo!='NULL'

То, что я хотел бы видеть в этом примере, будет:

Job_Number  User_Assigned   PendingInfo   PendingWord       PendingInfo  PendingWord

1           User1           01            Not Enough Info   02           Not Enough Time

Заранее спасибо

Ответы [ 6 ]

5 голосов
/ 10 мая 2010

Я надеюсь, что вы просто поддерживаете код, и это не новая реализация.
Пожалуйста, рассмотрите возможность использования другого подхода с использованием таблицы поддержки, например:

JOBS TABLE
jobID | userID
--------------
1     | user13
2     | user32
3     | user44
--------------

PENDING TABLE
pendingID | pendingText
---------------------------
01        | Not Enough Info
02        | Not Enough Time
---------------------------

JOB_PENDING TABLE
jobID | pendingID
-----------------
1     | 01
1     | 02
2     | 01
3     | 03
3     | 01
-----------------

Вы можете легко запросить эти таблицы, используя JOIN или подзапросы.
Если вам нужна ретро-совместимость в вашем программном обеспечении, вы можете добавить представление для достижения этой цели.

5 голосов
/ 10 мая 2010

Вы действительно не должны хранить несколько элементов в одном столбце, если ваш SQL когда-либо захочет обрабатывать их по отдельности. «Гимнастика SQL», которую вы должны выполнять в этих случаях, - это и отвратительные взломы, и снижение производительности.

Идеальное решение состоит в том, чтобы разделить отдельные элементы на отдельные столбцы и, для 3NF, переместить эти столбцы в отдельную таблицу в виде строк, если вы действительно хотите сделать это правильно (но, вероятно, все в порядке с детьми если вы уверены, что в краткосрочной и среднесрочной перспективе не будет более двух причин).

Тогда ваши запросы будут и проще, и быстрее.


Однако, если это не вариант, вы можете использовать вышеупомянутую гимнастику SQL, чтобы сделать что-то вроде:

where find ( ',' |fld| ',', ',02,' ) > 0

при условии, что в вашем диалекте SQL есть функция поиска строки (в данном случае find, но я думаю charindex для SQLServer).

Это обеспечит, чтобы все подколонки начинались и начинались с запятой (запятая плюс поле плюс запятая) и искали определенное желаемое значение (с запятыми с обеих сторон, чтобы обеспечить полное совпадение подколонок).


Если вы не можете контролировать то, что приложение помещает в этот столбец, я бы выбрал решение DBA - решения DBA определяются как решения, которые DBA должен делать, чтобы обойти недостатки своих пользователей : -.)

Создайте два новых столбца в этой таблице и создайте триггер вставки / обновления, который заполнит их двумя причинами, которые пользователь помещает в исходный столбец.

Затем запросите эти два столбца new для конкретных значений, а не пытайтесь разделить старый столбец.

Это означает, что стоимость разделения указана только для вставки / обновления строки, а не для _every single select`, что эффективно амортизирует эту стоимость.


Тем не менее, мой ответ - пересмотреть схему. Это будет лучший способ в долгосрочной перспективе с точки зрения скорости, читабельности запросов и удобства обслуживания.

3 голосов
/ 11 августа 2011

У меня есть таблицы вроде:

Events
---------
eventId int
eventTypeIds nvarchar(50)
...

EventTypes
--------------
eventTypeId
Description
...

Каждое событие может иметь несколько типов типов.

Все, что я делаю, это пишу 2 процедуры в коде моего сайта, а не в коде SQL

  1. Одна процедура преобразует значение поля таблицы (eventTypeIds), например "3,4,15,6", в массив ViewState, поэтому я могу использовать его в любом месте кода.

  2. Эта процедура делает противоположное, она собирает любые проверенные вами опции и преобразует их в

2 голосов
/ 10 мая 2010

Если изменение схемы является опцией (что, вероятно, должно быть), разве вы не должны реализовать здесь соотношение многие-ко-многим, чтобы между двумя элементами была таблица мостов? Таким образом, вы будете хранить номер и его формулировку в одной таблице, задания в другой и «причины сбоя задания» в таблице мостов ...

1 голос
/ 10 мая 2010

Посмотрите на похожий вопрос, на который я ответил здесь

;WITH Numbers AS 
( 
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS N
    FROM JobId
), 
Split AS 
( 
    SELECT JOB_NUMBER, USER_ASSIGNED, SUBSTRING(PENDING_INFO, Numbers.N, CHARINDEX(',', PENDING_INFO + ',', Numbers.N) - Numbers.N) AS PENDING_NUM
    FROM JobId
    JOIN Numbers ON Numbers.N <= DATALENGTH(PENDING_INFO) + 1 
    AND SUBSTRING(',' + PENDING_INFO, Numbers.N, 1) = ','
) 
SELECT *
FROM Split JOIN Pending ON Split.PENDING_NUM = Pending.PENDING_NUM

Основная идея заключается в том, что вы должны умножать каждую строку столько раз, сколько PENDING_NUM с. Затем извлеките соответствующую часть строки

0 голосов
/ 18 июля 2016

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

Допустим, у вас есть 10000 групп пользователей, каждая из которых имеет в среднем 1000 участников. Вы можете захотеть иметь таблицу user_groups со столбцами, такими как groupID и membersID. Ваш столбец membersID может быть заполнен следующим образом: (', 10,2001,20003,333,4520,') каждый номер является идентификатором участника, все разделены запятой. Добавьте также запятую в начале и конце данных. Тогда ваш выбор будет использовать как «%, someID,%».

Если вы не можете изменить свои данные ('01, 02,03 ') или аналогичные, допустим, что вам нужны строки, содержащие 01, вы все равно можете использовать "select ... LIKE '01,%' OR '%, 01' OR '% , 01,% '", что обеспечит совпадение, если в начале, в конце или внутри, при этом избегая аналогичного числа (то есть: 101).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...