AND (1=1) w zapytaniu - błąd czy optymalizacja?

1

Przed chwilą w ręce wpadło mi jakieś zestawienie faktur wygenerowane z poziomu ERP Optima.
Na dole zostało podane zapytanie, z którego skorzystano do wygenerowania tego zestawienia. Pomijam sensowność dawania tego na wydruku, ale ten wątek dotyczy czegoś innego. Zapytanie miało postać jak na poniższym obrazku oraz poniższym kodzie:

Zastosowano filtr: (((( BZd_Waluta = "" AND BZd_DataReal BETWEEN Convert(DATETIME,"2019-07-04 00:00:00",120)
AND Convert(DATETIME,"2022-05-20 00:00:00",120) AND NOT (BZd_Rozliczono=1 AND
BZd_Rozliczono2=2) AND BZd_Rozliczono<>2 AND BZd_Rozliczono<>0) AND (1=1)))) AND (Pod_Kod LIKE "%XXX%")

screenshot-20220523123126.png

I tak mnie zastanawia fragment podkreślony na zielono - czyli AND (1=1). Czy to jest jakaś sztuczka optymalizacyjna? Ma to jakiś sens, czy po prostu ktoś coś grzebał i zostawił ten (moim zdaniem) nic nie wnoszący do sprawy fragment?

@AdamWox: tak coś mi świta, że Ty działasz z Optimą. Kojarzysz, o co może tutaj chodzić?

6

IMO pewnie ktoś używa biblioteki do budowania zapytań i zrobił coś w stylu

Predicate p = Predicate.TRUE

if(cos){
  p.and(p2)
}

if(cos2){
 p.and(p3)
}

return p
9

Jest to bez znaczenia a pewnie bierze się z tego, że ktoś zawsze chciał mieć jakiegoś whera, bo np zapytanie jest sklejane na 6 różnych poziomach. Czyli nawet jak nie będzie żadnych filtrów na oknie, parametrów przekazanych do okna to i tak zapytanie będzie składniowo poprawne.

2

De facto jest to sztuczka optymalizacyjna. Do WHERE doklejany jest zawsze warunek AND ew. AND warunek. Chodzi o to, by nie sprawdzać za każdym razem, czy już coś w warunku jest (przy AND na początku), lub czy będzie w przyszłości (z AND na końcu). Wystarczy dodać warunek prawdziwy i na tym zakończyć WHERE.

0

@Marcin.Miga: szczerze mówiąc - nie rozumiem o czym piszesz.
Przecież skoro masz AND to znaczy, że wszystkie składowe muszą być true, inaczej całość będzie negatywna. Więc OK, tego 1=1 nie trzeba sprawdzać, ale wszystkie przed/po nim już tak. Możesz mi wytłumaczyć jeszcze raz, na czym ten zysk polega?

0

A to nie jest dzieło Comarchu?

Znając Comarch, to pewnie zrobili na sztywno, że zawsze jest ten "filtr", nawet jak jest pusty.
A jak jest pusty, to składnia musi się zgadzać, więc dali hack (1=1).
Ale pewnie nawet nie sprawdzają, czy filtr jest pusty, tylko zawsze doklejają to nieszczęsne (1=1).

Dałoby się to zrobić porządnie, no ale to przecież Comarch.
Asseco pewnie by zrobiło podobnie xD

4

Takie coś często się stosuje również przy dynamicznie generowanym SQL. Jak masz np filtry na GUI i nikt nic nie wybierze to masz sam select ... from tabela. Dodając jednak którykolwiek z filtrów musiałbyś sprawdzać czy jakikolwiek innych filtr został dodany aby nie było czegoś takiego

select ...
from tabela
and nazwa = 'xxx'

i to daje ci mnóstwo kodu
dodają zawsze where 1 = 1 czyli

select ...
from tabel
where 1 = 1

na każdym filtrze robisz tylko
and nazwa=wartość bez sprawdzania czy w select jest już where ;)

Nie mówię, że to jest dobre czy złe po prostu tłumaczę skąd się takie cuda biorą (spotkałem się z tym w kilku firmach i to w różnych językach czy to delphi czy php czy nawet java ;) )

1

@woolfik: no tak podejrzewałem, że to albo wynik jakiegoś generatora, albo niedbałość (ktoś coś grzebał i potem zapomniał pokasować), ale wolałem się upewnić. Czasem się jakieś takie dziwne sztuczki stosuje i mimo, że wydaje się to bezsensowne, to potrafi coś przyspieszyć albo obejść inny problem.

2
cerrato napisał(a):

@Marcin.Miga: szczerze mówiąc - nie rozumiem o czym piszesz.
Przecież skoro masz AND to znaczy, że wszystkie składowe muszą być true, inaczej całość będzie negatywna. Więc OK, tego 1=1 nie trzeba sprawdzać, ale wszystkie przed/po nim już tak. Możesz mi wytłumaczyć jeszcze raz, na czym ten zysk polega?

Marcinowi chyba chodzi o to, że składając zapytanie z warunek AND po ostatnim lub nie mając żadnego warunku nie musisz nic sprawdzać. Jak jest brak warunków to będzie AND (1=1) czyli poprawny, jak będzie AND (warunek=X AND warunek = Y AND) to musieli byśmy usunąć ostatni AND żeby nam parser się nie wysypał. Dodając 1=1 zawsze wiemy, że zapytanie będzie poprawne, niezależne od włożonych dynamicznie ilości warunków. Więc jest to sztuczka optymalizacyjna, ale nie dla samego silnika bazy danych, a dla kodu aplikacji która składa dynamicznie zapytanie.

1

Używałem kiedyś "i=i", bo była kwerenda z opcjami, i w minimalnym zestawie opcji by w ogóle nie było where.
Źle się to budowało, prościej było założyć że sekcja "where ..."" jest zawsze.

Dla kwerend powstających choć częściowo automatycznie dla mnie to jest zrozumiałe i akceptowalne

1

Taa, pytałem o to samo tutaj👌🤘

2
cerrato napisał(a):

I tak mnie zastanawia fragment podkreślony na zielono - czyli AND (1=1). Czy to jest jakaś sztuczka optymalizacyjna?

Pracowałem kiedyś z jednym chłopem, który w klauzuli WHERE dodawał zawsze WHERE 1 == 1. Wyjaśnił mi, że robi to tylko ze względów na czytelność. Tak wg niego czytelniej bo zawsze to where masz a warunki wymieniasz po AND...
Nie oceniam.

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