SQL-запрос с несколькими значениями в одном столбце

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

Job_Number     User_Assigned     PendingInfo

1              user1             01,02

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

Pending_Num    PendingWord

01             Not Enough Info
02             Not Enough Time

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

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

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

5
задан Tom H 8 July 2010 в 13:46
поделиться

4 ответа

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

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
ответ дан 18 December 2019 в 10:42
поделиться

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

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

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


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

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

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

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


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

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

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

Это означает, что затраты на разбиение связаны только с вставкой / обновлением строки, а не с каждым отдельным выбором, что эффективно снижает затраты.


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

5
ответ дан 18 December 2019 в 10:42
поделиться

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

2
ответ дан 18 December 2019 в 10:42
поделиться

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

;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 с. Затем извлеките соответствующую часть строки

1
ответ дан 18 December 2019 в 10:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: