InsERT GT => Dodatki - zestawienia - sfera => Wątek zaczęty przez: Lucus w Luty 22, 2022, 15:20:01
-
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_symboltym 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
-
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.chtCzyli łą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.
-
@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?
-
DISTINCT zlicza tylko unikalne wartości, jeśli dana wartość występuje np. 3 razy to zostanie policzona tylko raz.
-
Masz rację, distinct jest niepotrzebny i to tylko pozostałość ze sposobu w jaki próbowałem napisać tego joina wcześniej :)
-
@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
-
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.
-
@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
-
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.