MS SQL - modyfikacja zapytania

0

Witam.
Potrzebuję pomocy przy zmianie zapytania SQL

SELECT  *
FROM    dbo.TowaryWariantyKody
        LEFT JOIN ( SELECT  tps.IdMagazynu ,
                            SUM(tps.StanPartii) AS StanPartii ,
                            tp.IdWariantu
                    FROM    dbo.TowaryPartieStany AS tps
                            LEFT JOIN dbo.TowaryPartie AS tp ON tp.IdPartii = tps.IdPartii
							
							WHERE tps.IdMagazynu =1 -- przenieść do WHERE na końcu kodu

                    GROUP BY tp.IdWariantu ,
                            tps.IdMagazynu
                  ) AS ts ON ts.IdWariantu = TowaryWariantyKody.IdWariantu

WHERE ... -- przenieść tutaj

Nie mogę poradzić sobie ze przebudowaniem zapytania w taki sposób, aby warunek WHERE tps.IdMagazynu =1 znajdował się na końcu kodu - jest to konieczne. Oczywiście w obecnej postaci przeniesienie warunku zwraca już inny wynik. Poradźcie coś proszę.

0

Zwraca inny wynik i będzie zwracać inny wynik bo jest LEFT JOIN. Nie przeskoczysz tego.

0

Dlaczego jest to konieczne?

0
Marcin.Miga napisał(a):

Zwraca inny wynik i będzie zwracać inny wynik bo jest LEFT JOIN. Nie przeskoczysz tego.

A tam:

SELECT  *
FROM    dbo.TowaryWariantyKody
        LEFT JOIN ( SELECT  tps.IdMagazynu ,
                            SUM(tps.StanPartii) AS StanPartii ,
                            tp.IdWariantu
                    FROM    dbo.TowaryPartieStany AS tps
                            LEFT JOIN dbo.TowaryPartie AS tp ON tp.IdPartii = tps.IdPartii
                    GROUP BY tp.IdWariantu ,
                            tps.IdMagazynu
                  ) AS ts ON ts.IdWariantu = TowaryWariantyKody.IdWariantu

WHERE
    ts.IdMagazynu =1 or ts.IdMagazynu is null
0
Panczo napisał(a):
Marcin.Miga napisał(a):

Zwraca inny wynik i będzie zwracać inny wynik bo jest LEFT JOIN. Nie przeskoczysz tego.

A tam:

SELECT  *
FROM    dbo.TowaryWariantyKody
        LEFT JOIN ( SELECT  tps.IdMagazynu ,
                            SUM(tps.StanPartii) AS StanPartii ,
                            tp.IdWariantu
                    FROM    dbo.TowaryPartieStany AS tps
                            LEFT JOIN dbo.TowaryPartie AS tp ON tp.IdPartii = tps.IdPartii
                    GROUP BY tp.IdWariantu ,
                            tps.IdMagazynu
                  ) AS ts ON ts.IdWariantu = TowaryWariantyKody.IdWariantu

WHERE
    ts.IdMagazynu =1 or ts.IdMagazynu is null

W ten sposób już kombinowałem, ale taka modyfikacja zwraca inny wynik zapytania.
Warunek musi być na końcu, ponieważ stanowi CriteriaOperator dla obiektu XPServerCollectionSource (DevExpress), a pozostała część kodu SQL będzie tworzyła View w MSSQL.

0

W ten sposób już kombinowałem, ale taka modyfikacja zwraca inny wynik zapytania.

Podaj przykład różnicy, bo nie powinno się różnić

0
Panczo napisał(a):

W ten sposób już kombinowałem, ale taka modyfikacja zwraca inny wynik zapytania.

Podaj przykład różnicy, bo nie powinno się różnić

Spekulacja:
a) TowaryPartieStany - jakaś partia towaru nie jest umieszczona w magazynie -> idMagazynu IS NULL
b) Ten "górny" left join wyciągnie jakieś ekstra stany warianty kodu, dla którego idMagazynu IS NULL
c) możemy dostać coś więcej przez warunek idMagazynu IS NULL

Nie wiem jednak czy partia może być niezmagazynowana :)

0

@yarel w sumie racja, ale w takim razie zapytanie musiałoby brać tylko pozycje z wypełnionym magazynem, poza tym left join pomiedzy dbo.TowaryPartieStany a dbo.TowaryPartie powinien być zmieniony na inner join bo nie potrzebujemy czegoś bez idwariantu, tak wynika z tego joina: ts.IdWariantu = TowaryWariantyKody.IdWariantu

0

W wyniku zapytania zamierzam uzyskać:

  • zawsze wyświetlić wszystkie warianty towaru - Tabela TowaryWariantyKody. Ma to być pełna lista wariantów bez względu na to czy w tabeli TowaryPartieStany znajdują się wiersze dla danego wariantu.
  • dla tych wariantów zsumować stan dla każdego wariantu i magazynu: GROUP BY tp.IdWariantu , tps.IdMagazynu - Tabela TowaryPartieStany. Tabela TowaryPartie jest tylko po to, aby uzyskać IdWariantu partii (w tabeli TowaryPartieStany nie ma kolumny IdWariantu).
  • no i wybór magazyny ma być w ostatnim warunku Where na końcu kodu.
    @Panczo zmiana na inner join nie ma znaczenia, ponieważ jeśli istnieje partia to zawsze jest też stan. Dodam, że w tabeli TowaryWariantyKody może istnieć wiersz bez powiązanych wierszy w tabelach TowaryPartie i TowaryPartieStany - po prostu towar posiada warianty, a partie i stany pojawiają się dopiero przy przyjęciu towaru na magazyn.
0

No to czy w tabeli dbo.TowaryPartieStany rekordy gdzie IdMagazynu jest puste/null?

0

IdMagazynu jest zawsze określony - nie może być null.

0

to zapytam tylko czy warunek ts.IdMagazynu =1 or ts.IdMagazynu is null jest jedyny w WHERE

0
ts.IdMagazynu =1 or ts.IdMagazynu is null

to jedyn warunek.
OK - działa poprawnie, ale tylko jeśli istnieje 1 magazyn.
Więc:
Dla przykładu mam 2 magazyny, 1 towar posiadający 7 wariantów.
Na magazyn 1 przyjmowany jest towar(dla dwóch wariantów towaru): pojawiają siew wpisy do tabel TowaryPartie i TowaryPartieStany.
W tym momencie wykonuję powyższe zapytanie

SELECT  *
FROM    dbo.TowaryWariantyKody
        LEFT JOIN ( SELECT  tps.IdMagazynu ,
                            SUM(tps.StanPartii) AS StanPartii ,
                            tp.IdWariantu
                    FROM    dbo.TowaryPartieStany AS tps
                            LEFT JOIN dbo.TowaryPartie AS tp ON tp.IdPartii = tps.IdPartii
                    GROUP BY tp.IdWariantu ,
                            tps.IdMagazynu
                  ) AS ts ON ts.IdWariantu = TowaryWariantyKody.IdWariantu

WHERE
    (ts.IdMagazynu =1 or ts.IdMagazynu is NULL)

mag1.jpg

Wynik Ok - lista wszystkich 7 wariantów wraz z ich stanem magazynowym - StanPartii.

Teraz zapytanie dla magazynu 2

SELECT  *
FROM    dbo.TowaryWariantyKody
        LEFT JOIN ( SELECT  tps.IdMagazynu ,
                            SUM(tps.StanPartii) AS StanPartii ,
                            tp.IdWariantu
                    FROM    dbo.TowaryPartieStany AS tps
                            LEFT JOIN dbo.TowaryPartie AS tp ON tp.IdPartii = tps.IdPartii
                    GROUP BY tp.IdWariantu ,
                            tps.IdMagazynu
                  ) AS ts ON ts.IdWariantu = TowaryWariantyKody.IdWariantu

WHERE
    (ts.IdMagazynu =2 or ts.IdMagazynu is NULL)

mag2.jpg

Wynik zły - nie pokazuje wszytkich wariantów - są tylko te warianty towaru, dla których nie było przyjęcia na magazyn1 (zasługa ts.IdMagazynu is NULL). W wyniku pominięte są 2 warianty dla których było przyjęcie towaru na magazyn 1.
Bez dodania warunku or ts.IdMagazynu is NULL - w ogóle nie zwraca żadnych wierszy.
Tak jak już pisałem zależy mi, aby bez względu na to czy istnieją wiersze w tabeli TowarPartieStany - zawsze była zwracana lista wszystkich wariantów z ewentualnym stanem (GROUP BY tp.IdWariantu , tps.IdMagazynu) jeśli istnieje.

Jeśli WHERE tps.IdMagazynu = jest umieszczone przed GROUP BY to jest OK - ale tak jak wspomniałem muszę mieć na końcu kodu,

1

Rozumiem, ze musisz zrobić z tego view aby dopasować się do XPServerCollectionSource, pobieżnie analizując wychodzi, że nie da się mapować na funkcje tabelarayczną co byłoby najprosze, więc nie pozostaje nic innego tylko wyrzeźbić takie rozwiązanie, zakladając, że ZWASZE będziesz pytał o magazyn to posiłkując sie CROSS JOIN:

SELECT
       *
FROM
     (
     SELECT
            m.idMagazynu
          , twk.*
     FROM
          dbo.TowaryWariantyKody AS twk 
	   --zakładam że jest jakaś tabela z magazynami dla przykładu nazwałem ja Magazyny
          CROSS JOIN dbo.Magazyny AS m
) AS t
     LEFT JOIN
              (
     SELECT
            tps.IdMagazynu
          , SUM(tps.StanPartii) AS StanPartii
          , tp.IdWariantu
     FROM
          dbo.TowaryPartieStany AS tps
          LEFT JOIN dbo.TowaryPartie AS tp ON tp.IdPartii = tps.IdPartii
     GROUP BY
              tp.IdWariantu
            , tps.IdMagazynu
) AS ts ON ts.IdWariantu = TowaryWariantyKody.IdWariantu
           AND ts.IdMagazynu = t.IdMagazynu
WHERE 
	t.IdMagazynu = 1;

Ale rozważyłbym zmiane po stronie "klienta"

0

Tak będzie z tego widok, a warunek Where zostanie upchnięty W CriteriaOperator dla XPServerCollectionSource. W warunku zawsze będzie IdMagazynu więc zapytanie z CROSS JOIN działa tak jak chciałem.
@Panczo Wielkie Dzięki za Twoje zaangażowanie i drążenie tematu - bardzo mi pomogłeś! Dokładnie przewidziałeś nawet istnienie tabeli Magazyny:)
Jeśli chodzi o jakieś zmiany po stronie klienta to w moim przypadku (połączenie z bazą w trybie Server Mode) zostaje tylko skorzystanie z Common table expression w MSSQL i wówczas po stronie klienta możliwe będzie zrealizowanie dowolnego zapytania SQL.
Tu jest info o tym
https://www.devexpress.com/Support/Center/Example/Details/E3468/how-to-use-custom-sql-queries-as-a-data-source-in-xpo-via-common-table-expressions-cte
@Panczo jeszcze raz dzięki.

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