2010-05-10 17 views
5

Biłem sobie głowę na biurku, próbując to rozgryźć. Mam tabelę, która przechowuje informacje o zadaniu i powody, dla których praca nie jest zakończona. Powody są numeryczne, 01,02,03 itd. Możesz mieć dwa powody do oczekującej pracy. Jeśli wybierzesz dwa powody, zostaną one zapisane w tej samej kolumnie oddzielone przecinkiem. To jest przykład z jobid tabeli:Zapytanie SQL z wieloma wartościami w jednej kolumnie

Job_Number  User_Assigned  PendingInfo 

1    user1    01,02 

Jest inna tabela o nazwie Oczekuje, która przechowuje co rzeczywiście przedstawiają te wartości. 01 = Niewystarczająca ilość informacji, 02 = Za mało czasu, 03 = Czekanie na recenzję. Przykład:

Próbuję wykonać zapytanie do bazy danych, aby podać wszystkie numery stanowisk, użytkowników, informacje o oczekiwaniu i przyczyny oczekujące. Mogę przebić pierwszą wartość, ale nie mogę wymyślić, jak wykonać drugą. Co moje ograniczone umiejętności dotąd:

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' 

co chciałbym zobaczyć w tym przykładzie będzie:

Job_Number User_Assigned PendingInfo PendingWord  PendingInfo PendingWord 

1   User1   01   Not Enough Info 02   Not Enough Time 

góry dzięki

+0

Czy zmiana schematu jest opcją? Ta relacja powinna być albo tabelą odwzorowania, albo kolumną przyczyny wtórnej. –

+0

Baza danych 101 - ** pierwsza ** normalna forma (1NF): każdy wiersz/kolumna kolumny może zawierać co najwyżej ** jedną wartość **. –

Odpowiedz

2

Jeśli zmiana schematu jest opcja (co prawdopodobnie powinno być), czy nie powinieneś zaimplementować tutaj relacji wielu do wielu, aby mieć pomost między tymi dwoma przedmiotami? W ten sposób będziesz przechowywać numer i jego treść w jednej tabeli, zadania w innym, oraz "przyczyny niepowodzenia dla zleceń" w tabeli pomostowej ...

5

Naprawdę nie powinien przechowywać wielu pozycji w jednej kolumnie jeśli twój SQL kiedykolwiek będzie chciał przetwarzać je indywidualnie. "Gimnastyka SQL", którą musisz wykonać w tych przypadkach, to zarówno brzydkie hacki, jak i degradatory wydajności.

Idealnym rozwiązaniem jest podzielenie poszczególnych elementów na osobne kolumny i, dla 3NF, przeniesienie tych kolumn do osobnej tabeli jako wierszy, jeśli chcesz je wykonać poprawnie (ale kroki dla dzieci są prawdopodobnie w porządku, jeśli " na pewno nigdy nie będzie więcej niż dwa powody w perspektywie krótko- i średnioterminowej).

Wtedy twoje zapytania będą zarówno prostsze, jak i szybsze.


Jednakże, jeśli nie jest to opcja, można korzystać z wyżej wymienionych gimnastyka SQL zrobić coś takiego:

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

zakładając swój dialekt SQL posiada funkcję wyszukiwania string (find w tym przypadku , ale myślę, że charindex dla SQLServer).

Zapewni to, że wszystkie kolumny podrzędne zaczynają się i zaczynają od przecinka (przecinek plus pole plus przecinek) i szukają konkretnej pożądanej wartości (z przecinkami po obu stronach, aby upewnić się, że jest to pełna pod-kolumna).


Jeśli nie kontrola co stawia wniosek w tej kolumnie, chciałbym zdecydować się na rozwiązanie DBA - Rozwiązania DBA są zdefiniowane jako te, DBA musi zrobić, aby obejść niedoskonałości swoich użytkowników :-).

Utwórz dwie nowe kolumny w tej tabeli i wykonaj wyzwalacz wstawiania/aktualizacji, który zapełni je dwoma przyczynami, które użytkownik umieszcza w oryginalnej kolumnie.

Następnie należy wysłać zapytanie do tych dwóch nowych kolumn dla konkretnych wartości, zamiast próbować podzielić starą kolumnę.

Oznacza to, że koszt podziału jest tylko przy wstawianiu/aktualizowaniu wiersza, a nie przy każdym pojedynczym wyborze, amortyzuje to kosztowo.


Nadal moją odpowiedzią jest ponowne wykonanie schematu. To najlepszy sposób na dłuższą metę, jeśli chodzi o szybkość, czytelne zapytania i łatwość konserwacji.

+0

Tak, odtworzenie byłoby najlepszym sposobem, ale to nie jest opcja w tym momencie. To jest sytuacja, z którą muszę pracować. Przepraszam, zapomniałem wspomnieć, że to jest MS SQL 2008 – lp1

+0

Następnie powiedz swoim szefom, że to kiepski pomysł, a następnie spróbuj opcji 'charindex'. A jeśli wydajność jest do dupy, możesz powiedzieć swoim szefom, że masz rację, a oni byli idiotami, mam nadzieję, że z większym wyczuciem niż zwykle jestem w stanie :-) – paxdiablo

+0

Postaram się, aby spróbować tego charindexu. – lp1

5

Mam nadzieję, że po prostu utrzymujesz kod i nie jest to zupełnie nowa implementacja.
Proszę rozważyć użycie innego podejścia przy użyciu tabeli support tak:

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 
----------------- 

Można łatwo kwerendy to tabele używając JOIN lub podzapytania.
Jeśli potrzebujesz oprogramowania w stylu retro, możesz dodać widok, aby osiągnąć ten cel.

1

spojrzeć na podobne pytanie odpowiedziałem here

;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 

Podstawowym założeniem jest to, że trzeba pomnożyć każdy wiersz tyle razy, ile jest PENDING_NUM s. Następnie wyodrębnić odpowiednią część napisu

3

Mam tabele jak:

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

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

Każde zdarzenie może mieć wiele eventtypes określone.

Wszystko mogę zrobić, to napisać 2 Procedury w kodzie witryny, a nie kod SQL

  1. Jedna procedura przekształca pole tabeli (eventTypeIds) wartość jak „3,4,15,6” do tablicy viewstate , więc mogę go użyć gdziekolwiek w kodzie.

  2. Procedura ta ma przeciwnego zbiera żadnych opcjach sprawdzonych i zamienia go w

0

Chociaż zgadzam się z perspektywy DBA nie przechowywać wiele wartości w jednym polu jest to wykonalne, jak mieszka, praktyczny dla logiki aplikacji i niektórych problemów z wydajnością.

Powiedzmy, że masz 10000 grup użytkowników, z których każda ma średnio 1000 członków. Możesz chcieć mieć tabelę user_groups z kolumnami takimi jak groupID i membersID. Twoja kolumna membersID może być wypełniona w następujący sposób: (', 10,2001,20003,333,4520,'), przy czym każda liczba jest identyfikatorem, oddzielonym przecinkiem. Dodaj także przecinek na początku i na końcu danych. Wtedy twój wybór użyłby "%, someID,%".
Jeśli nie możesz zmienić swoich danych ('01, 02,03 ') lub podobnych, powiedzmy, że chcesz wiersze zawierające 01, nadal możesz użyć "wybierz ... LIKE '01,%' LUB '%, 01' LUB "%, 01,%" ", który zapewni, że pasuje, jeśli na początku, na końcu lub w środku, unikając jednak podobnej liczby (tj .: 101).

Powiązane problemy