Ciągle zapominam o tym terminie, ponieważ pojawia się on bardzo rzadko, ale tak czy inaczej, twoje indeksy nie mogą być zoptymalizowane za pomocą funkcji MIESIĄC() i ROK(), ponieważ są one funkcjami na danych bazowych. Stosując datę RANGE, mogą. Możesz więc zachować swój miesiąc/rok, tak jakby coś zostało utworzone w styczniu 2021 i zaktualizowane w marcu 2021, ale dodatkowo dodając "i c.date_created>=current_date AND current_date <=c.date_updated" , MOŻESZ wykorzystać indeks, jeśli zawiera on datę utworzenia (mniej ważne w tym przypadku dla daty aktualizacji.Podobnie do drugiej tabeli.
Ponadto, gdy masz sprzężenie lewe ze stołu „a” do tabeli „c”, to zastosowanie gdzie, to prawie tak, jakbyś próbował wymusić łączenie, ale pozostaje lewy ze względu na OR.
Przeniosłbym warunek oparty na "c" do lewego łączenia, a następnie po prostu przetestował znaleziony tam rekord jako NULL lub nie.
Chociaż nie jest to jasne (nie zostało to wyjaśnione, kiedy zapytałem), MYŚLĘ, że kiedy tworzony jest nowy rekord „A”, system może faktycznie umieścić datę utworzenia zarówno w dacie utworzenia, jak i dacie aktualizacji. JEŚLI TAK JEST, to wystarczy odpytać/odnieść się do ostatniego zaktualizowanego pola daty z bieżącym miesiącem/rokem działalności. Jest to teraz wymóg PRIMARY dla klauzuli WHERE — NIEZALEŻNIE od podstawowego warunku LUB w tabeli „C”.
Dodatkowo, ponieważ month() i year() nie są sargeable (Dzięki Ollie), wykonuję wstępne zapytanie, aby uzyskać początek bieżącego i przyszłego miesiąca, abym mógł zbudować
WHERE > beginning of this month and LESS than beginning of next month
Jeśli chodzi o indeksy, zacząłbym aktualizować
loan_applications_tbl ( date_created, date_updated, loan_status, current_loan, ippis )
topup_or_reapplication_tbl ( ippis, status, current_loan, date_created, date_updated )
Ostatnie zapytanie do wypróbowania.
SELECT
a.id,
a.user_unique_id,
a.loan_location,
a.ippis,
a.tel_no,
a.organisation,
a.branch,
a.loan_agree,
a.loan_type,
a.appr,
a.sold,
a.loan_status,
a.top_up,
a.current_loan,
a.date_created,
a.date_updated,
c.loan_id,
c.user_unique_id tu_user_unique_id,
c.ippis tu_ippis,
c.top_up_approved,
c.loan_type tu_loan_type,
c.dse,
c.status,
c.current_loan tu_current_loan,
c.record_category,
c.date_created tu_date_created,
c.date_updated tu_date_updated
FROM
-- this creates inline mySQL variables I can use for the WHERE condition
-- by doing comma after with no explicit join, it is a single row
-- and thus no Cartesian result, just @variables available now
( select
-- first truncating any TIME portion by casting to DATE()
@myToday := date(curdate()),
@howFarBack := date_sub( @myToday, interval 6 month ),
-- now subtract day of month -1 to get first of THIS month
@beginOfMonth := date_sub( @myToday, interval dayOfMonth( @myToday ) -1 day ),
-- and now, add 1 month for beginning of next
@beginNextMonth := date_add( @beginOfMonth, interval 1 month ) ) SqlVars,
loan_applications_tbl a
LEFT JOIN topup_or_reapplication_tbl c
ON a.ippis = c.ippis
AND c.current_loan='1'
AND c.status IN ('pending', 'corrected', 'Rejected',
'Processing', 'Captured', 'Reviewed', 'top up')
AND
(
(@beginOfMonth <= c.date_created
AND c.date_created < @beginNextMonth)
OR
(@beginOfMonth <= a.date_updated
AND a.date_updated < @beginNextMonth )
)
WHERE
-- forces only activity for the single month in question
-- since the "a" table knows of any "updates" to the "C",
-- its updated basis will keep overall restriction to any accounts
-- updated within this month in question only
-- testing specifically for created OR updated within the
-- current month in question
a.date_created >= @howFarBack
AND
(
(@beginOfMonth <= a.date_created
AND a.date_created < @beginNextMonth)
OR
(@beginOfMonth <= a.date_updated
AND a.date_updated < @beginNextMonth )
)
-- and NOW we can easily apply the OR without requiring
-- to run against the ENTIRE set of BOTH tables.
AND (
c.ippis IS NOT NULL
OR
( a.loan_status IN ( 'pending', 'corrected', 'Rejected', 'Processing',
'Captured', 'Reviewed', 'top up')
AND (
a.current_loan = '1'
OR ( a.current_loan = '0'
AND a.loan_status IN ('Approved', 'Closed')
)
)
)
)
KOMENTARZE KOŃCOWE DO ZAPYTANIA
Zmodyfikowałem zapytanie, a także indeks podstawowy w pierwszej tabeli, aby INCLUDE (pierwsza pozycja) data utworzenia rekordu. Dodałem również dodatkową zmienną @howFarBack, aby była to maksymalny czas powrotu do rozważenia przy pożyczce. Zwlekałem z 6 miesięcy wstecz. Czy kiedykolwiek musiałbyś rozważyć pożyczkę na konto starsze niż 6 miesięcy? A może konto „a” rejestruje coś, co może sięgać 10 lat wstecz i warto je uwzględnić? Mam wrażenie, że jest to nowa data dodania WNIOSKU KREDYTOWEGO. Jeśli tak, umożliwienie cofnięcia się o 6 miesięcy wstecz przed zatwierdzeniem, sfinalizowaniem i anulowaniem nadal uniemożliwiłoby przejrzenie tylu miesięcy danych w przeszłości.
W klauzuli WHERE dodałem wyraźny dodatek dla CREATED_DATE>=@howFarBack. Nigdy nie byłoby możliwe utworzenie rekordu podrzędnego, nie mówiąc już o aktualizacji w dowolnym momencie przed pierwotną datą dodania. Wymusi to zakwalifikowanie się tylko do aktywności w bieżącym miesiącu LUB DO PRZODU.
Np.:utwórz pożyczkę 28 kwietnia. Uruchamiając zapytanie, początek miesiąca to 1 kwietnia, ale MNIEJ niż 1 maja (pozwala to na uwzględnienie 30 kwietnia o 23:59:59)
Teraz wkraczamy w maj, a zmiana kredytu następuje 4 maja. Jesteśmy w nowym miesiącu, a @howFarBack nadal pozwala starszym aplikacjom do grudnia 2020 r. BYĆ MOŻLIWE zakwalifikować się w porównaniu z całą tabelą aplikacji, które mogą sięgać roku 2005, o ile wiemy. Zawsze pozostajesz z najbardziej aktualnymi danymi i możesz łatwo zmienić @howFarBack jako maksymalny czas powrotu. Powinno to pomóc w spełnieniu Twoich potrzeb w zakresie wydajności.