Dublowanie rekordów po left join

Dublowanie rekordów po left join
BI
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 9 lat
  • Postów:18
0

Mam widoki, z który chce wyciągnąć dane. Chce mieć połączone dane.
Tabela A wygląda:
Indeks ilość
aaa 1
bbb 2
ccc 3
ddd 4 itd

Tabela B wygląda
Indeks kolor
aaa bialy
aaa bialy
bbb czarny
bbb czarny
ccc zielony
ddd niebieski

Kopiuj
select A.indeks,a.ilosc,b.kolor from tabelaA 
left join tabelaB on a.indeks=b.indeks 

Problem polega na tym że dla indeksów aaa, bbb, które są podwójnie w tabeli B dostaję podwójne rekordy.
Jak się przed tym zabezpieczyć?

edytowany 1x, ostatnio: bizzy
BS
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 10 lat
  • Postów:22
0

Nie jestem przekonany, jaki efekt chcesz osiągnąć.
Czy przećwiczyć złączenie JOIN, czy wybrać dane? :)
Nie wiem także, na jakim motorze bazy danych pracujesz, ale jeżeli jest to MySQL, to zadziała takie coś

Kopiuj
SELECT 
  TableA.`indeks` AS klucz, 
  TableA.`ilosc`,  
  TableB.`kolor` 
FROM TableA, TableB
WHERE TableA.`indeks` = TableB.`indeks` GROUP BY klucz

To też powinno zadziałać:

Kopiuj
SELECT 
  TableA.`indeks` AS klucz, 
  TableA.`ilosc`, 
  (SELECT TableB.`kolor` FROM TableB WHERE TableB.`indeks` = klucz GROUP BY `indeks`)
FROM TableA

oraz to również:

Kopiuj
SELECT 
  TableB.`indeks` AS klucz, 
  TableB.`kolor`, 
  (SELECT TableA.`ilosc` FROM TableA WHERE TableA.`indeks` = klucz )
FROM TableB GROUP BY klucz

Zwróć proszę uwagę na to, że klauzula GROUP BY po jakimś polu powoduje, że wybrane wartości są unikalne w tej kolumnie.
Teraz już dowolnie, czy najpierw wybierzesz dane z tabeli B i spowodujesz, że nie będą się dublowały wartości (dodając GROUP BY na indeks, czy też wybierzesz w pierwszej kolejności dane z tabeli A i uzupełnisz je informacjami z tabeli B

Mała rada na przyszłość:

  1. Nie używaj polskich "ogonków" w nazwach tabel i kolumn (iloŚĆ),
  2. Nie używaj nazw "niebezpiecznych" ;-) w nazwach tabel i kolumn (np "index")

I jeszcze jedno, gdy tak patrzę na te tabele i ich zawartość.
Sądzę, że powinieneś połączyć je w jedną tabelę (kolumnaIndex, KolumnaKolor, KolumnaIlosc) i zadeklarować KolumneIndex jako klucz główny (PK) . Wydaje mi się, że wskazane byłoby także, by kolumna z kolorami była unikalna.

....Ale nie wiem do czego to stosujesz i jakie masz potrzeby, więc potraktuj to jako luźne propozycje ;-)

Oops! :(
Zauważyłem, że stoi znaczek "oracle" przy Twoim poście, więc mój wtręt "nie wiem, na jakiej bazie pracujesz" jest lekko nieaktualny ;-) ....ale sądzę, że moje zapytania na tym motorze też zadziałają.

Na marginesie, Twój przykład:

Kopiuj
SELECT A.indeks,a.ilosc,b.kolor FROM tabelaA 
LEFT JOIN tabelaB ON a.indeks=b.indeks 

zmodyfikowałbym:

Kopiuj
SELECT a.`indeks`, a.`ilosc`, b.`kolor` FROM tabelaA a 
LEFT JOIN TabelaB b ON a.indeks = b.indeks
GROUP BY `indeks`

a jak się głębiej temu przyjrzysz, to zwrócisz uwagę, że na Twoje potrzeby (unikalności po kolumnie indeks) nie ma znaczenia, czy wykonujesz złączenie lewostronne (LEFT) czy prawostronne (RIGHT).

Dla aktualnej zawartości tabel A i B, poniższy kod też powinien dać ten sam efekt, co we wcześniejszym przykładzie

Kopiuj
SELECT a.`indeks`, a.`ilosc`, b.`kolor` FROM tabelaA a 
RIGHT JOIN TabelaB b ON a.indeks = b.indeks
GROUP BY `indeks`

.... i samo JOIN też chyba zaskoczy (... tak na 99,99% ;-))

Kopiuj
SELECT a.`indeks`, a.`ilosc`, b.`kolor` FROM tabelaA a 
JOIN TabelaB b ON a.indeks = b.indeks
GROUP BY `indeks`
edytowany 13x, ostatnio: BSorbus
BI
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 9 lat
  • Postów:18
0

Wiesz te tabele były tylko na zasadzie przykładu i wyglądają one zupełnie inaczej. W rzeczywistości mam jedną tabelą, w której mam indeks, nazwa_klienta, ilosc, wartosc i wiele innych danych sprzedażowych oraz drugą bazę, w której do każdego indeksu przypisane są różne cechy takie jak kolor, kształt, format, grubość i ilość dostępna na magazynie. itp. ale indeksy te powtarzają się przez wzgląd ze występują na różnych magazynach pozostałe cechy są identyczne, czyli jeśli produkt leży na pięciu magazynach to jest 5 rekordów takich samych różniących się tylko magazynem i ilością dostępną.
Chcę np. wyciągnąć dane o wielkości sprzedaży np. Indeksów dla których produkty są żółte i niebieskie to chcę dociągnąć kolor, ale tu pojawia się problem, że jeśli
indeksu aaa sprzedało się 10szt to po join -ie koloru, jeśli ten produkt jest na 4 magazynach robią się cztery rekordy
aaa 10 zołty
aaa 10 zołty
aaa 10 zołty
aaa 10 zołty
Jeśli produkt jest tylko na jednym magazynie problem ten nie występuje.
Także group by tu nic nie da, bo zwinie mi to do jednego rekordu tu zgoda, ale ilość którą otrzymam to 40, a naprawdę sprzedało się 10.
Na tym polega mój kłopot.

edytowany 1x, ostatnio: bizzy
C8
  • Rejestracja:prawie 12 lat
  • Ostatnio:23 dni
  • Postów:80
0

To może zrób jedną bazę dla wszystkich magazynów i dodaj kolumnę z nr_magazynu do tabeli.
I do tego stwórz triggera, który będzie automatycznie dla każdego magazynu dodawał numer magazynu.
Spróbuj tęz pokombinować z DISTNICT.

BS
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 10 lat
  • Postów:22
0
bizzy napisał(a):

Wiesz te tabele były tylko na zasadzie przykładu i wyglądają one zupełnie inaczej......

Wiesz....
Ustosunkowałem się do Twojego problemu podwójnych wystąpień po Selekcie dla struktur i danych, które przedstawiłeś.
Mam nadzieję, że moje przykłady były jasne i wyczerpujące. :)

Nie znam struktury Twojego magazynu i w związku z tym nie podejmuję się dalszego sugerowania czegokolwiek. :(

Pozdrawiam i powodzenia.

Zobacz pozostałe 4 komentarze
BS
W 1) SELECT TableA.indeks AS klucz, TableA.ilosc,<br /> TableB.kolor FROM TableA, TableB WHERE TableA.indeks = TableB.indeks GROUP BY klucz Złe grupowanie, gdyż? 2) SELECT TableA.indeks AS klucz, TableA.ilosc, (SELECT TableB.kolor FROM TableB WHERE TableB.indeks = klucz GROUP BY indeks) FROM TableA A jakie to mogę się zdarzyć te wartości skoro Tabela A (tak wynika z prezentowanego przykładu) ma PK na kolumnie indeks? Podasz?<br /> 3) Pytania jak powyżej 4) Aliasy .... to chyba nie tylko w przykładzie 4-tym, ale we wszystkich.
BS
<quote="1043910">Wiesz te tabele były tylko na zasadzie przykładu i wyglądają one zupełnie inaczej. W rzeczywistości mam jedną tabelą, w której mam indeks, nazwa_klienta, ilosc, wartosc i wiele innych danych sprzedażowych oraz drugą bazę, w której do każdego indeksu przypisane są różne cechy takie jak kolor, kształt, format, grubość i ilość dostępna na magazynie. </quote> - chyba ten opis (i przykład z pierwszego posta) nie pozostawia wątpliwości, że Tabela A jest unikalna po kolumnie indeks, a Tabela B ma dzieci w relacji do tabeli A
BS
"To że zapytania działają to nic nie znaczy. Mają zwracać prawidłowe wartości." - rozumiem, że mamy się odnosić do tego konkretnego przypadku, a nie do związków tabel, gdzie Tabela A ma także możliwość dublowania wartości w kolumnie "indeks"?
Marcin.Miga
Pliz, nie ośmieszaj się - doczytaj.
BS
Taaaaak..... Tej argumentacji nie obalę. :) Miłego dnia :)
Marcin.Miga
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 3 godziny
  • Postów:2792
0

A żeby nie było, że tylko krytykuję:

Kopiuj
SELECT A.indeks,a.ilosc,b.kolor FROM tabelaA a
LEFT JOIN (SELECT DISTINCT Indeks, kolor FROM tabelaB) b ON a.indeks=b.indeks 
BS
Jeszcze gwoli wyjaśnienia moich grupowań, to nieśmiało stwierdzam, że ten przykład też "wciągnie" zdublowane wartości jeżeli Tabela A nie ma unikalności na kolumnie "indeks" ;-) Zatem podajesz przykład, który a priori zakłada taką unikalność, a kwestionujesz, że ja takie założenie przyjąłem? :-O
BS
To może jednak podasz jakiś przykład danych, gdzie nieprawidłowo moje zapytania zadziałają, a Twój przykład wytrzyma "próbę ognia"? :) ... a wtedy będziemy sobie wstawiali komentarze "....nie ośmieszaj się" ;-) :D - Kolejny przypadek, gdzie dyskusja na argumenty zamienia się w akcje "...nie ośmieszaj się". Żenujące
BS
Podajesz w przykładzie: "create table tabelaa ( indeks varchar(20) not null primary key, ilosc int not null ); "czyli definiujesz na tabeli A jednak unikalność na kolumnie indeks..... Więc, kto jest śmieszny?
BS
Zdjąłem CI tam PK i dodałem ('aaa', 11) i co? Wywaliło zdublowane 'aaa'! :D :D :D Powtarzam, że przyjąłeś dokładnie takie same założenia jak ja, tylko że GŁUPOTY piszesz o moim grupowaniu, to raz. Dwa, samemu napisałeś zapytanie, które na brak unikalności "index" w Tabeli A odporne nie jest. Gdybym był złośliwy, to zaproponowałbym "nie ośmieszaj się, plizz".... ale ponieważ nie jestem, więc zwykłe "Sorki, przeoczenie" - też mi wystarczy ;-) Co to w ogóle za maniera na forum? Nie można od razu podać przykładu, z którego jednoznacznie wynika, że ...król jest nagi?
BS
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 10 lat
  • Postów:22
0

Tak na marginesie, zechcesz się podzielić wiedzą, czym różni się Twoje zapytanie od mojego:

SELECT
TableA.indeks AS klucz,
TableA.ilosc,
(SELECT TableB.kolor FROM TableB WHERE TableB.indeks = klucz GROUP BY indeks)
FROM TableA

Chętnie zapoznam się z "kluczowymi różnicami" (szczególnie gdy wyświetlisz explain query) dla fragmentów
SELECT DISTINCT Indeks, kolor FROM tabelaB - w Twoim zapytaniu
(SELECT TableB.kolor FROM TableB WHERE TableB.indeks = klucz GROUP BY indeks) - i w moim

edytowany 2x, ostatnio: BSorbus
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
BSorbus napisał(a):

Tak na marginesie, zechcesz się podzielić wiedzą, czym różni się Twoje zapytanie od mojego:

SELECT
TableA.indeks AS klucz,
TableA.ilosc,
(SELECT TableB.kolor FROM TableB WHERE TableB.indeks = klucz GROUP BY indeks)
FROM TableA

To jest zapytanie skorelowane, które wykonane zostanie dla każdego wiersza z TableA. I to nie jest fajne...
@Marcin.Miga pokazał inny sposób - złączenie jest wykonane do wyniku, który odrzuca powtórzone rekordy.

Także, jego wersja powinna być szybsza - ale wiele zależy od silnika bazy danych...
Chętnie zapoznam się z "kluczowymi różnicami" (szczególnie gdy wyświetlisz explain query) dla fragmentów
SELECT DISTINCT Indeks, kolor FROM tabelaB - w Twoim zapytaniu
(SELECT TableB.kolor FROM TableB WHERE TableB.indeks = klucz GROUP BY indeks) - i w moim

Rożnica jest opisana na górze, a generalnie nalezy unikać takich konstrukcji jak Twoja.
Są naprawdę lepsze sposoby.
Tak na marginesie - żaden podany w tym wątku nie wyczerpuje pytania i każdy posiada błędne założenie.
Dlaczego wychodzicie od TabelaA skoro powinno się wyjść od TabelaB, bo tam są istotne dane o sprzedaży?

@bizzy, możesz dokładnie wyjaśnić co masz na myśli pisząc:

Jeśli produkt jest tylko na jednym magazynie problem ten nie występuje.
Także group by tu nic nie da, bo zwinie mi to do jednego rekordu tu zgoda, ale ilość którą otrzymam to 40, a naprawdę sprzedało się 10.

Jak jednoznacznie określić że coś się sprzedało? Ja rozumiem to tak, że Ty chcesz dostać dane które się sprzedały - czyli dokładnie jak wybrałbyś (jakie muszą spełnić warunki) takie dane z TabelaB?
A więc najpierw należy wybrać to co się sprzedało z TabelaA a dopiero potem dołączyć dane z TabelaB.

BS
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 10 lat
  • Postów:22
0

"....To jest zapytanie skorelowane, które wykonane zostanie dla każdego wiersza z TableA. I to nie jest fajne..."
Dogmatycznie podchodząc do sprawy masz 100% racji, ale.....
Zostanie wykonane dla każdego WYBRANEGO wiersza, bo chyba nie mamy wątpliwości, że nakładając warunek WHERE TabelaA coś tam, nie zostanie wykonane DLA KAŻDEGO wiersza z całej TableA, tylko dla każdego wiersza z WYBRANEGO kursora.

" .....co przy założeniu Twoim (i moim!): "A więc najpierw należy wybrać to co się sprzedało z TabelaA a dopiero potem dołączyć dane z TabelaB. winno dać oczekiwany efekt."

  • zatem chyba właśnie takiego efektu oczekujemy? ;-)

"@Marcin.Miga pokazał inny sposób - złączenie jest wykonane do wyniku, który odrzuca powtórzone rekordy.
Także, jego wersja powinna być szybsza - ale wiele zależy od silnika bazy danych..."

  • Dobrze byłoby gdyby jego wersja faktycznie odrzucała powtórzone rekordy w TabeliA.
    Jego zapytanie nie jest odporne na to, a to właśnie zarzucił mojemu "gorszemu" rozwiązaniu.

"Tak na marginesie - żaden podany w tym wątku nie wyczerpuje pytania i każdy posiada błędne założenie.
Dlaczego wychodzicie od TabelaA skoro powinno się wyjść od TabelaB, bo tam są istotne dane o sprzedaży?"

  • Może dlatego, że zapytanie tak zostało skonstruowane?
    Zwróć proszę uwagę na fakt, że głównym zmartwieniem pytającego były zdublowane "aaa biały, bbb czarny" na liście wyników, temat brzmi "Dublowanie rekordów po left join",
    .....a nie stawia on pytania, jak elegancko policzyć sprzedane towary...

"Jak jednoznacznie określić że coś się sprzedało? Ja rozumiem to tak, że Ty chcesz dostać dane które się sprzedały"

  • założenie może i słuszne, ale jeżeli kolega chce dostać też listę z pozycjami "= 0" sprzedaży?
edytowany 2x, ostatnio: BSorbus
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)