MSSQL - CASE prawdziwy w obydwóch przypadkach - jeden wynik. Jak to obejść.

0

Witam
Mam problem z wyrażeniem SELECT i znajdującym się w nim warunku CASE.
Już się przekonałem że CASE działa tak że w momencie gdy pierwszy warunek jest prawdziwy nie sprawdza już reszty warunków.
Ale mam do napisania raport w którym obydwa warunki mogą być (i w praktyce często są) prawdziwe. W takim przypadku dostaje tylko rekordy spełniające pierwszy warunek.

Generalnie chodzi o to że zapytanie ma w kontekście transportu wyciągnąć:
RODZAJ_DODATKU - ten może wynikać automatycznie z cennika, lub być wprowadzony ręcznie przez użytkownika. W zależności od sytuacji wstawiana ma być wartość 'CENNIK' lub 'MANUALNIE'.

KOD_DODATKU - jeśli wynika z cennika wstawiana jest wartość 'SUMA DODATKOW Z CENNIKA', jeśli został wprowadzony manualnie przez użytkownika jego kod jest pobierany z odpowiedniej tabeli.

WARTOSC_DODATKU - pobierana w zależności od kodu dodatku z odpowiednich tabel.

Jak pisałem wyżej bardzo często jest tak że na danym transporcie występują obydwa rodzaje dodatku.

Poniżej przykładowe zapytania i wyniki:

Uwzględnione tylko dodatki manualne:

SELECT
	NUMER_ZT		= TR.TR_NUMBER
,   RODZAJ_DODATKU	= case
						   when TBC.TBC_ID				is not null then 'MANUALNIE'
						   when TR.TR_BONUS_COST		is not null then 'CENNIK'
						   end

,	KOD_DODATKU		= case
						   when KOD_DODATKU_OA.MSG_TEXT is not NULL then KOD_DODATKU_OA.MSG_TEXT
						   when TR.TR_BONUS_COST		is not NULL then 'SUMA DODATKOW Z CENNIKA'
						   end

,	WARTOSC_DODATKU	= case
						   when TBC.TBC_VALUE			is not NULL then CAST (TBC.TBC_VALUE AS DECIMAL (15,2))
						   when TR.TR_BONUS_COST		is not NULL then TR.TR_BONUS_COST
						   end

FROM TRANSPORT					as TR			with (nolock)
left join TRANSPORT_BONUS_COST	as TBC			with (nolock) on TR.TR_ID = TBC.TBC_TR

	   outer apply(
             select top 1
             MD.MSG_TEXT
             from MESSAGE_DATA				as MD		with (nolock)
			 inner join DICTIONARY_DETAIL	as DD		with (nolock) on DD.DD_MSG_UID = MD.MSG_UID and MD.MSG_LANG = 1045
             where TBC.TBC_DD_BONUS = DD.DD_ID
       )KOD_DODATKU_OA

where TR.TR_NUMBER = 'TK14585'

screenshot-20210401183143.png

Uwzględnione tylko dodatki wynikające z cennika:

SELECT
	NUMER_ZT		= TR.TR_NUMBER
,   RODZAJ_DODATKU	= case 
						   when TR.TR_BONUS_COST		is not null then 'CENNIK'
						   when TBC.TBC_ID				is not null then 'MANUALNIE'
						   end

,	KOD_DODATKU		= case 
						   when TR.TR_BONUS_COST		is not NULL then 'SUMA DODATKOW Z CENNIKA' 
						   when KOD_DODATKU_OA.MSG_TEXT is not NULL then KOD_DODATKU_OA.MSG_TEXT
						   end

,	WARTOSC_DODATKU	= case 
						   when TR.TR_BONUS_COST		is not NULL then TR.TR_BONUS_COST
						   when TBC.TBC_VALUE			is not NULL then CAST (TBC.TBC_VALUE AS DECIMAL (15,2))
						   end

FROM TRANSPORT					as TR			with (nolock)
left join TRANSPORT_BONUS_COST	as TBC			with (nolock) on TR.TR_ID = TBC.TBC_TR

	   outer apply(
             select top 1
             MD.MSG_TEXT
             from MESSAGE_DATA				as MD		with (nolock)
			 inner join DICTIONARY_DETAIL	as DD		with (nolock) on DD.DD_MSG_UID = MD.MSG_UID and MD.MSG_LANG = 1045
             where TBC.TBC_DD_BONUS = DD.DD_ID
       )KOD_DODATKU_OA

where TR.TR_NUMBER = 'TK14585'

screenshot-20210401183214.png
Co więcej nie za bardzo rozumiem dlaczego w drugim przypadku dostaje pięć rekordów zamiast jednego, bo w tabeli TRANSPORT jest zawsze jeden rekord do każdego numeru transportu.

Docelowo wynikiem zapytania powinno być łącznie sześć rekordów - pięć z dodatkiem manualnym i jeden dodatkiem wynikającym z cennika.

Nie za bardzo wiem jak to połączyć w jedną całość.
Być może rozwiązaniem może być jakaś konstrukcja zapytania skorelowanego, ale nie wiem czy to dobry kierunek.
Proszę o pomoc i jakieś podpowiedzi.

0

Tak bez specjalnego wgłębiania się użył bym 3 warunku sprawdzającego czy oba warunki są spełnione tj;

RODZAJ_DODATKU  = case 
                           when TR.TR_BONUS_COST  is not null AND TR.TR_BONUS_COST is not null THEN 'Cennik i Manualnie'
                           when TR.TR_BONUS_COST        is not null then 'CENNIK'
                           when TBC.TBC_ID              is not null then 'MANUALNIE'
                           end

I analogicznie dla każdej kolumny tak - jeśli wartość liczbowa to sumujesz.

0
BlackBad napisał(a):

Tak bez specjalnego wgłębiania się użył bym 3 warunku sprawdzającego czy oba warunki są spełnione tj;

RODZAJ_DODATKU  = case 
                           when TR.TR_BONUS_COST  is not null AND TR.TR_BONUS_COST is not null THEN 'Cennik i Manualnie'
                           when TR.TR_BONUS_COST        is not null then 'CENNIK'
                           when TBC.TBC_ID              is not null then 'MANUALNIE'
                           end

I analogicznie dla każdej kolumny tak - jeśli wartość liczbowa to sumujesz.

Niestety wynik ma być zawsze podzielony na rodzaje dodatku, a więc oddzielnie wiersze z dodatkiem manualnym i wynikającym z cennika. Dlatego napisałem że docelowo wynikiem zapytania powinno być łącznie sześć rekordów - pięć z dodatkiem manualnym i jeden dodatkiem wynikającym z cennika.

1

Join jaki by nie był nie zrobi Ci magicznie dwóch wierszy z jednego...
To co chcesz osiągnąć trzeba by było zrobic unionem

0

@Panczo: Przepraszam że odpisuje z takim opóźnieniem. UNION w prosty sposób rozwiązał problem w SSMS.

I teraz pytanie które nadawałoby się na nowy temat, ale jeszcze zapytam tutaj. Czy można w Report Builder analogicznie jak w zapytaniu połączyć dwa zestawy danych (DataSet) ze sobą poprzez coś na kształt UNION?
Całość przenoszę na raport i mam problem bo hurtownia danych działa w openquery gdzie jest ograniczenie do 8000 znaków w zapytaniu. A moje zapytanie poprzez wyciąganie dużej ilości kolumn, joinów i dodanie UNION po którym jest praktycznie to samo przekracza tą ilość.
Wiem że można to obejść wywołaniem procedury w której będzie cały SELECT, ale to jest dla mnie ostateczność, bo polityka IT w tym zakresie zakłada tworzenie jak najmniejszej ilości procedur.
Jeżeli trzeba to zadam to pytanie w nowym wątku.

0

Nie znam ReportBuildera więc nie pomogę.

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