IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Filtrace dostupných možností dle zvolených kritérií

V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Adam Gajdečka:9.2.2021 12:39

Ahoj, jsem už dost zoufalý. Snažím se v LINQ napsat dotaz na db, abych získal možnosti a počty možností, které lze vybrat. Jde o groupBy zřejmě. Chci ať to funguje stejně jako na Alze.

Na mém webu filtruje uživatel pneumatiky dle růzměrů apod. Když vybere nějakou šířku, chci mu zobrazit už jen dostupné profily, průměry apod. Zároveň, například u vybrané šířky potřebuji spočítat možnosti u nevybraných šířek. Tudíž abych získal možnosti šířek, i když už mám nějakou zvolenou, tak musím vycházet z dat, které šířku nepodmínkují. Možná to vysvětluji složitě, snad vám to bude jasné, jak to má fungovat.

Klidně mi ukažte nějaký příklad obyčejného SQL. Používám Microsoft databázi.

Děkuji

Zkusil jsem: vůbec to neumím napsat v jednom dotazu..

 
Odpovědět
9.2.2021 12:39
Avatar
Jakub Švasta
Lektor
Avatar
Odpovídá na Adam Gajdečka
Jakub Švasta:9.2.2021 22:25

S EF nepracuju, ale když nikdo neodpovídá, zkusím pomoct aspoň s klasickým SQL.

Nejsem si jistý, jak to myslíš s tím jedním dotazem. Podle mě potřebuješ pro naplnění každého comba samostatný select, který bude vypadat nějak takhle:

SELECT PW.Id, PW.[Description], COUNT(P.Id) AS [Count]
FROM PneuWidth PW
LEFT OUTER JOIN Pneu P ON P.PneuWidthId = PW.Id
        AND P.PneuDiameterId = ISNULL(@PneuDiameterId, P.PneuDiameterId)
        AND P.PneuProfileId = ISNULL(@PneuProfileId, P.PneuProfileId)
        AND P.PneuSpeedIndexId = ISNULL(@PneuSpeedIndexId, P.PneuSpeedIndexId)
        -- atd
GROUP BY PW.Id, PW.[Description]
HAVING COUNT(P.Id) > 0          -- tenhle radek tam dej jen kdyz chces vynechat nedostupne moznosti
ORDER BY PW.[Description]

Když uživatel něco vybere, pro každé combo znovu zavoláš jeho select a do parametrů @PneuDiameterId apod. vyplníš to, co uživatel vybral v ostatních combech. Kde nic nevybral, tam bude NULL, čímž se příslušná podmínka neaplikuje.

Celkový počet dostupných produktů bych si vytáhl samostatným jednoduchým selectem:

SELECT COUNT(1) AS TotalCount
FROM Pneu P
WHERE P.PneuDiameterId = ISNULL(@PneuDiameterId, P.PneuDiameterId)
        AND P.PneuProfileId = ISNULL(@PneuProfileId, P.PneuProfileId)
        AND P.PneuSpeedIndexId = ISNULL(@PneuSpeedIndexId, P.PneuSpeedIndexId)
        -- ... atd, stejne jako vys

Pokud předem víš, že nebudeš chtít ukazovat kategorie, kde zbylo 0 produktů, dá se to udělat buď tím HAVING výše, nebo takhle, což by snad mělo být trochu rychlejší:

SELECT PW.Id, PW.[Description], COUNT(1) AS [Count]
FROM PneuWidth PW
LEFT OUTER JOIN Pneu P ON P.PneuWidthId = PW.Id
WHERE P.PneuDiameterId = ISNULL(@PneuDiameterId, P.PneuDiameterId)
        AND P.PneuProfileId = ISNULL(@PneuProfileId, P.PneuProfileId)
        AND P.PneuSpeedIndexId = ISNULL(@PneuSpeedIndexId, P.PneuSpeedIndexId)
        -- atd
GROUP BY PW.Id, PW.[Description]
ORDER BY PW.[Description]

Na obrázcích máš dummy ukázku s filtrem a bez filtru.

Editováno 9.2.2021 22:28
 
Nahoru Odpovědět
9.2.2021 22:25
Avatar
Adam Gajdečka:10.2.2021 16:23

Děkuji moc. Zkusím se od tohoto odpíchnout :-)

 
Nahoru Odpovědět
10.2.2021 16:23
Avatar
Odpovídá na Jakub Švasta
Adam Gajdečka:10.2.2021 17:12

Takže pro každou vlastnost ve filtraci, musím mít jeden select dotaz? To znamená, že Alza jich má desítky? Jelikož jejich filtrace obsahuje nespočet parametrů.

 
Nahoru Odpovědět
10.2.2021 17:12
Avatar
Odpovídá na Jakub Švasta
Adam Gajdečka:10.2.2021 19:12

Pro doplnění. Já tabulku mám jen jednu a to Products se všemi vlastnostmi pneumatik atd. O co mi od začátku jde, jak vytáhnout z ní všechny možnosti pro selectBoxy co nejefektivněji. Nejsem v tom moc znalý, předpokládal jsem, že to půjde vytáhnout jedním dotazem, na to se tady ptám. Děkuji

 
Nahoru Odpovědět
10.2.2021 19:12
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:11.2.2021 11:48

Pokud mas 10 selectboxu, tak mas 10 sql dotazu.
Pokud je v tom problem, muzes to udelat jednim s UNION. Pro upravy a jednoduchost je ale lepsi mit kazdy ciselnik (staty, okresy, mesta a pod) mit zvlast. Samozrejme, je to o neco pomalejsi a vadi to tam, kde mas limit na pocet sql dotazu za hodinu. Tak, na takovem hostingu nic neprovozuji :)

SELECT id, value, 0 AS type FROM tabulka1
UNION ALL
SELECT id, value, 1 AS type FROM tabulka2
UNION ALL
SELECT id, value, 2 AS type FROM tabulka3

U unionu je ale podstatne, ze musis mit stejny pocet sloupcu.

 
Nahoru Odpovědět
11.2.2021 11:48
Avatar
Jakub Švasta
Lektor
Avatar
Odpovídá na Adam Gajdečka
Jakub Švasta:12.2.2021 21:01

Promiň za zdržení v odpovědi, měl jsem toho hodně v práci. Samozřejmě to do jednoho výsledku spojit můžeš, pak bude mít asi takovouhle strukturu:

Combo Moznost NovyPocet
PneuSpeedIndex T 2
PneuSpeedIndex U 1
PneuWidth 205 3
PneuWidth 215 2
... ... ...

Dotaz pak může vypadat asi takhle:

WITH P AS
(
        SELECT P.Id, P.PneuWidth, P.PneuDiameter, P.PneuProfile, P.PneuSpeedIndex
        FROM Products P
        WHERE P.PneuWidth = ISNULL(@PneuWidth, P.PneuWidth)
                AND P.PneuDiameter = ISNULL(@PneuDiameter, P.PneuDiameter)
                AND P.PneuProfile = ISNULL(@PneuProfile, P.PneuProfile)
                AND P.PneuSpeedIndex = ISNULL(@PneuSpeedIndex, P.PneuSpeedIndex)
)
SELECT 'PneuWidth' AS Combo, P.PneuWidth AS [Option], COUNT(P.Id) AS [Count]
FROM P
GROUP BY P.PneuWidth
UNION ALL
SELECT 'PneuDiameter' AS Combo, P.PneuDiameter AS [Option], COUNT(P.Id) AS [Count]
FROM P
GROUP BY P.PneuDiameter
UNION ALL
...

Fakticky to je pořád tolik selectů, kolik máš comboboxů, jinak se to nedá udělat, protože každý groupuje podle něčeho jiného. Ten union je jen takový fejk, jak to spojit do jednoho recordsetu. Jak píše Peter Mlich, dej si pozor, že všechny selecty v unionu musejí vracet přesně stejné sloupce.
Ale protože máš jedinou tabulku, bude aspoň profiltrovaný obsah pro všechny ty selecty stejný, takže ho můžeš vyčlenit do společné CTE (to je ta část za WITH), a v každém z těch selectů ho znovu využít.

V aplikaci pak podle comba a hodnoty dohledáš položku a aktualizuješ u ní číslo. U položek, které ve výsledku obsažené nebudou, nastavíš 0.

Jestli jde tohle nějak udělat LINQem, resp. EF nevím, a i kdyby to šlo, nevím, jak rychlé to bude.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
12.2.2021 21:01
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.