Autor Wątek: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech  (Przeczytany 2347 razy)

0 użytkowników i 1 Gość przegląda ten wątek.

Offline Lucus

  • Nowy użytkownik
  • *
  • Wiadomości: 48
  • Reputacja +0/-0
  • Wersja programu: Subiekt Gt 1.70
Hej,

Czy da się napisać zestawienie tak, aby wyświetlało towary, które spełniają wszystkie opcje zaznaczone w kontrolce CHL_DB?
Przykład:
Towar_1 posiada przypisane cechy A, B, C, D
Towar_2 posiada przypisane cechy A, B, D, E
Towar_3 posiada przypisane cechy B, C, E

I chciałbym móc w zestawieniu zaznaczyć w kontrolce CHL_DB cechy B i C, tak żeby finalnie zostały wyświetlone następujące towary:
Towar_1
Towar_3

Wpadłem tylko na dwa pomysły, ale jeden jest zbyt skomplikowany, a drugi nie do końca wiem jak zrobić:
1 sposób: Użycie dwóch kontrolek DB i napisanie zestawienia tak, żeby w jednej kontrolce wybierać cechę B, a w drugiej C przy zastosowaniu INTERSECT
2 sposób:
SELECT tw_symbol, COUNT(*)
FROM tw__towar

INNER JOIN
tw_CechaTw ON cht_IdTowar = tw_Id and cht_IdCecha IN (22,41)

GROUP BY tw_symbol
tym sposobem INNER JOIN ogranicza wyświetlane towary do zawierających przynajmniej jedną z cech z kontrolki (dla uproszczenia podałem teraz tylko dwie wartości w nawiasach), a COUNT policzy ile razy występuje dany towar.
Wtedy gdybym w HAVING porównał wartość COUNT = ILE OPCJI ZOSTAŁO WYBRANYCH to otrzymałbym tylko te wartości, które zawierają wszystkie zaznaczone wartości.
Nie wiem niestety jak (i czy się da) wyliczyć ilość wybranych opcji.
Tak, że np. jak ktoś w kontrolce CHL_DB wybierze opcje "Przykład_1", "Przykład_2", "Przykład_3" to wyświetli wartość "3" ponieważ trzy opcje są wybrane

Offline PrzemekP

  • Nowy użytkownik
  • *
  • Wiadomości: 33
  • Reputacja +2/-0
  • Wersja programu: 1.60
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #1 dnia: Luty 23, 2022, 16:06:14 »
Można to zrobić np. w taki sposób:

select tw_Symbol, tw_Nazwa
from tw__Towar

left join (select distinct cht_idTowar, count(cht_idCecha) [cht] from tw_CechaTw
where cht_idCecha in ({CHL_DB:select ctw_id, ctw_Nazwa from sl_cechaTw:Cecha:1:xx})
group by cht_idTowar)x on x.cht_idTowar = tw_id

where
(select count(ctw_Nazwa) [ileCech] from sl_CechaTw
where ctw_id in ({CHL_DB:select ctw_id, ctw_Nazwa from sl_cechaTw:Cecha:1:xx})
) = x.cht
Czyli łączymy do towarów counta z ilości wybranych w filtrze cech będących jednocześnie cechami tego towaru, a w warunku Where porównujemy tego counta z drugim countem liczącym wszystkie wybrane cechy.

Offline Lucus

  • Nowy użytkownik
  • *
  • Wiadomości: 48
  • Reputacja +0/-0
  • Wersja programu: Subiekt Gt 1.70
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #2 dnia: Luty 24, 2022, 13:22:06 »
@PrzemekP Działa, Dziękuję za odpowiedź :)
W ramach edukacyjnych analizuję linijkę po linijce kodu jaki przesłałeś i mam na początek takie pytanie:
... select distinct cht_idTowar, count(cht_idCecha) ...Co nam w tym kodzie daje DISTINCT. Czy to nie działa w taki sposób, że COUNT "grupuje" nam id cechy w jeden wiersz, a użycie później GROUP BY cht_idTowar grupuje nam w jeden wiersz id towaru?

Offline yemet

  • Zaawansowany użytkownik
  • ****
  • Wiadomości: 1254
  • Reputacja +46/-1
  • Wersja programu: Navireo
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #3 dnia: Luty 24, 2022, 16:25:47 »
DISTINCT  zlicza tylko unikalne wartości, jeśli dana wartość występuje np. 3 razy to zostanie policzona tylko raz.

Offline PrzemekP

  • Nowy użytkownik
  • *
  • Wiadomości: 33
  • Reputacja +2/-0
  • Wersja programu: 1.60
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #4 dnia: Luty 24, 2022, 16:28:11 »
Masz rację, distinct jest niepotrzebny i to tylko pozostałość ze sposobu w jaki próbowałem napisać tego joina wcześniej :)

Offline Lucus

  • Nowy użytkownik
  • *
  • Wiadomości: 48
  • Reputacja +0/-0
  • Wersja programu: Subiekt Gt 1.70
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #5 dnia: Luty 25, 2022, 12:27:36 »
@PrzemekP
A tak się zastanawiam jeszcze.
Skoro służy to ograniczaniu wybranych opcji nie mogę tego zawrzeć w INNER JOIN?
INNER JOIN
(
    SELECT
        DISTINCT cht_idTowar,
        COUNT(cht_idCecha) AS Cecha

    FROM tw_CechaTw

    WHERE cht_idCecha IN ({CHL_DB:SELECT ctw_id, ctw_Nazwa FROM sl_cechaTw:Cecha:22:BL})

    GROUP BY cht_idTowar
) AS cechaTabela
ON cechaTabela.cht_idTowar = tw_id
    AND
        SELECT COUNT(ctw_Nazwa) [ileCech]
        FROM sl_CechaTw
        WHERE ctw_id in ({CHL_DB:SELECT ctw_id, ctw_Nazwa FROM sl_cechaTw:Cecha:22:BL})
        )

Pytanie ogólnie ze względu na ciekawość.
Są jakieś wytyczne co do dobrych praktyk? Np. żeby każde JOIN robić osobno albo wszystkie sklecić np. w jeden INNER JOIN (np. gdy chcemy mieć kontrolki Grupy, cechy itp.)
Bo tak ogólnie to widzę, że mogę sobie to rozpisać na bardzo wiele sposobów.
Ze względu na kolejność elementów na górnej belce wpierw pobieram sobie dane, które mnie głównie interesują w pierwszym FROM, ale z konkretnej grupy, a później w JOIN z cechy
SELECT
tw_Symbol
FROM
(
    SELECT *
    FROM tw__towar
    WHERE
            tw_IdGrupa IN ({CHL_DB: SELECT -1, '(dowolna)' AS nazwaGrupy UNION ALL SELECT grt_Id, grt_Nazwa AS nazwaGrupy FROM sl_GrupaTw ORDER BY nazwaGrupy:Grupa:-1:(dowolna)})
        OR
            -1 IN ({CHL_DB: SELECT -1, '(dowolna)' AS nazwaGrupy UNION ALL SELECT grt_Id, grt_Nazwa AS nazwaGrupy FROM sl_GrupaTw ORDER BY nazwaGrupy:Grupa:-1:(dowolna)}) --Dwie kontrolki (CHL_DB) mają na celu wymusić domyślnie wybraną opcję [dowolna]
) AS Grupa

Czy to zła praktyka? Bardzo w teorii to już w pierwszym from w taki sposób jak powyżej mogę ograniczyć bardzo mocno dane do większości interesujących mnie kontrolek

Offline yemet

  • Zaawansowany użytkownik
  • ****
  • Wiadomości: 1254
  • Reputacja +46/-1
  • Wersja programu: Navireo
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #6 dnia: Luty 25, 2022, 12:34:09 »
Ze względu na kolejność elementów na górnej belce wpierw pobieram sobie dane, które mnie głównie interesują w pierwszym FROM, ale z konkretnej grupy, a później w JOIN z cechy

Piszesz o kolejności filtrów? Skopiuj same filtry i przeklej je na samą górę zapytania, poukładaj w kolejności jaka cie interesuje i całość zakomentuj  :)
Ułożą się w kolejności jak zostały podane na samym początku zapytania i to, że są zakomentowane w niczym im nie przeszkadza.
Ja staram się większość filtrów upychać do where.
« Ostatnia zmiana: Luty 25, 2022, 12:37:01 wysłana przez yemet »

Offline Lucus

  • Nowy użytkownik
  • *
  • Wiadomości: 48
  • Reputacja +0/-0
  • Wersja programu: Subiekt Gt 1.70
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #7 dnia: Luty 25, 2022, 12:57:46 »
@yemet
 :o
To tak się da? :D
A ja zawsze się męczę i piszę jakieś dziwactwa, żeby górna belka filtrów mi się w odpowiedniej kolejności ułożyła :P

Offline Lucus

  • Nowy użytkownik
  • *
  • Wiadomości: 48
  • Reputacja +0/-0
  • Wersja programu: Subiekt Gt 1.70
Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #8 dnia: Luty 25, 2022, 13:12:33 »

Ja przyjąłem sobie zasadę, że staram się wszystko umieszczać w tym bloku tekstu, którego to dotyczy.
Z tego powodu w WHERE na końcu kodu staram się umieszczać to co jest ogólne lub dotyczy tak jakby całości (ostatecznie stworzonej tabelii).
I z tego też powodu to co podał @PrzemekP z chęcią dałbym w INNER JOIN - wtedy mam wszystko w jednym miejscu i nie musze później szukać po co został dopisany jakiś fragment w WHERE na końcu
W miarę mi się to sprawdzało przy pisaniu rzeczy, które mają bardzo dużo kodu, ale nie wiem czy jest to jakkolwiek poprawnie bo nigdy się SQLa nie uczyłem, bazuje na bieżąco na dokumentacji i próbuje zrozumieć jak to działa.

Forum Użytkownikow Subiekt GT

Odp: Zestawienie z towarami spełniające wszystkie warunki odnośnie cech
« Odpowiedź #8 dnia: Luty 25, 2022, 13:12:33 »