[SQL] Trudne zapytanie select

0

Mam problem,
w tabeli są dwie kolumny, i czasami jedna kolumna przechowuje kilka słów po przecinku np:

słowo1, słowo2, słowo3

innym razem ta sama kolumna przechowuje tylko jeden wyraz np:

słowo5

pytanie brzmi: jak się odnieść do danego wiersza za pomocą tylko slowa2 albo slowa1 ?

Oto przykład zapytania, które zwraca wynik, tylko wtedy gdy podam wszystkie trzy słowa czyli całą zawartość kolumny:

  string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE @pol";
            
            SqlCeCommand Polecenie = new SqlCeCommand(Zapytanie, con);
            
            Polecenie.Parameters.Add("@pol", textBox1.Text);

jak wpiszę w TextBox tylko jedno z słów np: slowo3 to wynik zapytania nic nie zwraca :-(

Proszę o pomoc, sugestie, albo gdzie szukać rozwiązania

0

Może pomyśl najpierw o normalizacji bd, bo z tego co pisze Twoja baza danych nawet nie jest w I postaci normalnej.

0

Nie mam pojęcia jak się zabrać do normalizacji...poza tym musiałbym przebudować jeszcze inne rzeczy :-(
hmm.. ale też nie da się tu zrobić normalizacji tak na prawdę, bo jest to po prostu słownik i w każdym wierszu jest wartość kolumny "pol" i wartość kolumny "ang" a często się zdarza że jakieś słówko ma kilka tłumaczeń właśnie po przecinku..

Wiem że są zapytania w SQL opierające się na kombinacji różnych znaków specjalnych, za pomocą których wystarczy wpisanie jednego wyrazu z np. trzech wyrazów, a i tak odnajdzie cały wiersz i pięknie wyświetli :-)

Przykładowo, mam słówko "ARM" które posiada kilka tłumaczeń na język polski: konar, broń, ręka, ramię, herb, poręcz, odnoga tłumacząc z języka polskiego na angielski chciałbym wpisać tylko słowo ręka a funkcja SQL powinna wyszukać ten ciąg znaków i wyświetlić angielskie słówko , gdybym normalizował tę bazę to zrobiło by się duo więcej słówek o tych samych angielskich tłumaczeniach..bez sensu :-)

0
SELECT * FROM user.tablela WHERE kolumna like '%slowo1%';
0

koziołek - dokładnie o to mi chodziło !!

ale niestety nie zadziała to z parametrem

 string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE '%@pol%'";

jak się nazywają takie funkcje ??

0

string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE '%"+@pol+"%'";

Niestety cała konstrukcja nie jest najlepsza bo te zapytanie będzie zwracać również wynik dla słowa którego częścią jest warunek. Np. dla słowa 'but' zwróci 'but', 'butik', 'szkorbut' itp.

0

AdamPl- '%" + @pol + "%'

" The name 'pol' does not exist in the current context "

po dodaniu cudzysłów '%" +" @pol" + "%' , kompiluje się ale nic nie zwraca zapytanie

0

a nie powinno być coś w stylu (znalezione w starym podręczniku do Visual Basica):

SELECT * FROM user.tabela WHERE kolumna like '%" & @param & "%';
0

hmm.. ale też nie da się tu zrobić normalizacji tak na prawdę, bo jest to po prostu słownik i w każdym wierszu jest wartość kolumny "pol" i wartość kolumny "ang" a często się zdarza że jakieś słówko ma kilka tłumaczeń właśnie po przecinku.

Da się normalizacje bez problemu przeprowadzić, tylko pytanie czy to ma sens ze względu na wydajność.

0

Przemyślenie po nocy... skoro to jest słownik to inaczej należało by podejść do struktury bazy.
Mamy sobie taką oto tabelki:
słowo_polskie

  • id - long PK
  • słowo - varchar
  • znaczenia - text
  • odpowiednik_ang - long FK

słowo_ang

  • id - long PK
  • słowo - varchar
  • znaczenia - text
  • odpowiednik_pol - long FK

i teraz załóżmy, że szukamy słowa w języku polskim i chcemy je przetłumaczyć na angielski. Wystarczy zatem coś w rodzaju:

Select słowo_polskie.słowo, słowo_polskie.znaczenia, słowo_ang.słowo from słowo_polskie, słowo_ang where słowo_polskie.słowo like 'słowo_szukane' and słowo_polskie.id = słowo_ang.id;

nie jestem pewien co do składni i wydajności, ale całą noc w robocie spędziłem. Generalnie mam nadzieję, że idea jest zrozumiała.

0
Koziołek napisał(a)

Przemyślenie po nocy... skoro to jest słownik to inaczej należało by podejść do

nie jestem pewien co do składni i wydajności, ale całą noc w robocie spędziłem. Generalnie mam nadzieję, że idea jest zrozumiała.

Dzięki za pomoc, z tym że nie tak łatwo mi będzie stworzyć taką właśnie strukturę, bo ja to importuje z pliku txt ..

ale taki kod działa poprawnie:

        string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE  @pol";
        
        SqlCeCommand Polecenie = new SqlCeCommand(Zapytanie, con);
        
        Polecenie.Parameters.Add("@pol","%" + textBox1.Text + "%" );

, podpowiedź od chłopaka z codeguru

Dzięki za pomoc , koniec tematu [soczek]

0

"Chłopak z Codeguru" to ja. Ciekawe określenie swoją drogą. Nawet lepsze od "dziecko .NET", które też ostatnio usłyszałem :D

Wracając do tematu i projektu bazy - taki byłby zły?
http://img152.imageshack.us/img152/5323/bazaslownikqc6.png

@Koziołek - jaki jest sens nadawania id typu long? Przecież int może mieć wartość maksymalną ponad 2mld - chyba wystarcza na słownik, przecież nie ma tylu słów. Już raczej w tabeli Pozycje zrobić id typu bigint, bo kombinacji słów może być wiele.

@kiniu - chyba warto pomyśleć przy robieniu bazy, żeby była ona sprawna oraz poprawna. To, że trudniej będzie wrzucić ten plik do bazy, no cóż - coś za coś. Ale nie jest to niewykonalne. Po prostu wczytując każde słowo polskie i angielskie trzeba będzie sprawdzić, czy jest już bazie, jeśli jest, to pobrać jego ID. Jeśli nie, to dodać je, a następnie dodać nowe powiązanie w tabeli Pozycje. Chyba wszystko.

0

@somekind - kluczem głównym w tabeli pozycje może być id_slowa_angielskiego + id_slowa_polskiego

0
AdamPL napisał(a)

@somekind - kluczem głównym w tabeli pozycje może być id_slowa_angielskiego + id_slowa_polskiego

Wtedy można by zrezygnować z ID_pozycji

Dzięki za wszystkie odpowiedzi, każdą przekalkulowałem i wypróbowałem.

Ale na prawdę nie będę zmieniał mojej struktury, jest ona prosta i czytelna: dwie kolumny "pol" i "ang" :-)
Jestem naprawdę za bardzo ograniczony (nie tylko umysłowo [green] ) żeby to teraz przerabiać..

Dla mojej struktury Takie rozwiązanie jest najbardziej zadowalające:

Polecenie.Parameters.Add("@pol","%" + textBox1.Text + "%"); by Chłopak z CodeGuru :-D

Jedyne co jest irytujące,(co prawda jest to rzadkość) to to że wyniki które wyświetlam w DataGrid nie zawsze są w 100 % poprawne. Dla przykładu, wpisując do textBox1 słowo "chleb",DataGrid wyświetla kilka pierwszych haseł w stylu: "przypochlebiać się" , "pochlebca" dopiero któreś słowo z kolei to właściwe "chleb".

Czy nie ma jakiejś metody żeby tak sformatować wynik zapytania, aby na początku wyświetlał 100 % podobieństwa, a potem korzystał z doklejania "%" ?

Proszę o pomoc, pisałem że zapytanie będzie trudne!
;-P

EDIT: wystarczyło dodać order by:

string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE  @pol order by pol ";
0

Nie ma. Sam pisałeś, że może być jedno słowo, a równie dobrze może być kilka. W takim wypadku dodawania spacji czy przecinka przed/po słowie również mija się z celem. Zmień strukturę tabel na taką jaką Ci zaproponowano i unikniesz takich problemów.

EDIT: wystarczyło dodać order by:
string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE @pol order by pol ";

Nie wystarczy.

0
AdamPL napisał(a)

@somekind - kluczem głównym w tabeli pozycje może być id_slowa_angielskiego + id_slowa_polskiego

W zasadzie wiem (z wykładów ;)), że jest taka możliwość, ale nigdy do tej pory tego nie używałem, więc nie chciałem źle podpowiedzieć.

0
AdamPL napisał(a)

EDIT: wystarczyło dodać order by:
string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE @pol order by pol ";

Nie wystarczy.

Dobra skłamałem jest na to sposób ale mało profesjonalny:
SELECT * FROM slownik WHERE pol LIKE @pol order by len(pol)

Samo order by pol zwróci posortowane alfabetycznie, a order by len(pol) zwróci posortowane od najkrótszego wyrazu, a akurat najkrótszy wyraz to dokładnie ten którego szukasz.

0
AdamPL napisał(a)
AdamPL napisał(a)

EDIT: wystarczyło dodać order by:
string Zapytanie = "SELECT * FROM slownik WHERE pol LIKE @pol order by pol ";

Nie wystarczy.

Dobra skłamałem jest na to sposób ale mało profesjonalny:
SELECT * FROM slownik WHERE pol LIKE @pol order by len(pol)

Samo order by pol zwróci posortowane alfabetycznie, a order by len(pol) zwróci posortowane od najkrótszego wyrazu, a akurat najkrótszy wyraz to dokładnie ten którego szukasz.

tak, czy siak gdy na przykład będę szukał tłumaczenia "chlebodawca" to najpierw pokaże mi "chleb", ale juz przeboleje to :-)

@AdamPL - napisz proszę przykładową definicję w SQL takiego połączonego z dwóch ID klucza , z projektu somekinda

0

@kiniu, ale jak szukasz chlebodawca to najkrótszym wzorcem będzie właśnie chlebodawca i chleb nie powinien się pojawić. Inaczej ma się sprawa jeżeli szukasz dopasowania po wzorcu wtedy nie ma metody na znalezienie dopasowania. Można by pokombinować ze scoringiem, ale to dość dużo pracy. W dodatku mało się sprawdza, bo trzeba by było zmuszać usera do kliknięcia na najbardziej prawidłowej opcji.

0
kiniu napisał(a)

@AdamPL - napisz proszę przykładową definicję w SQL takiego połączonego z dwóch ID klucza , z projektu somekinda

To będzie coś w ten deseń...

Create TABLE Pozycje
(
  id_slowa_polskiego int CONSTRAINT PK_Pozycje PRIMARY KEY 
  (id_slowa_polskiego, id_slowa_angielskiego), 
  id_slowa_angielskiego int
)
0

Dziękuję, do połowy rozumiem, a resztę się douczę w wolnej chwili.

1 użytkowników online, w tym zalogowanych: 0, gości: 1