Pobranie danych z dwóch tabel, jeśli nie ma powiązania zwróć null

0

W mojej relacyjnej bazie danych mam dwie tabele.
Chciałbym pobrać wszystkie wpisy z tabeli1 oraz tylko jedną kolumnę z tabeli2.
Jeśli między tymi tabelami nie ma powiązania (nie ma rekoru w tabeli2), to chciałbym aby pobierana kolumna przyjęła wartość null.

Tutaj demo:
http://sqlfiddle.com/#!9/4f7fb3/5/0

Aktualnie pobieram wszystko z tabeli1, a następnie w pętli for pobieram dane z tabeli2. Jeśli wartość istnieje, to ją wpisuje, jeśli nie to pomijam.
Niestety jest to bardzo czasochłonne zadanie dlatego też zrobienie tego w jednym zapytaniu powinno znacząco wpłynąć na czas wykonania całego skryptu.
Zależy mi na możliwie jak najszybszym pobraniu rekordów z tych dwóch tabel.

2

Chodzi o zwyczajnego left join-a?

SELECT t1.*, t2.value 
FROM table1 t1 
LEFT JOIN table2 t2 ON t2.id_table1 = t1.id
0

Na to wygląda.
Zwraca dane w takiej formie jak chciałem.
Jeszcze jedno pytanie, czy zamiast null można zwrócić np wartość 0?

1

@NewUser2k13:

SELECT 
  t1.*
  , IFNULL(t2.value, 0) AS value
FROM table1 t1 
LEFT JOIN table2 t2 ON t2.id_table1 = t1.id
0

@twoj_stary
To jeszcze jedno pytanie, bo niestety zamiast pomóc, to się ponad 2x wydłużył czas zapytania
W tym zapytaniu pojawia się także WHERE
SELECT t1.*, t2.value FROM t1 LEFT JOIN t2 ON t1.id = t2.id_t1 WHERE YEAR(date)=2023 ORDER BY t1.id DESC

Czy coś robię źle? Dla około 1500 rekordów czas trwania zapytania to ponad 19sek....

0
NewUser2k13 napisał(a):

Czy coś robię źle? Dla około 1500 rekordów czas trwania zapytania to ponad 19sek....

Uhmmmm ...
Ale na nieznanej strukturze to nikt ci nie powie

0

@AnyKtokolwiek

To co zauważyłem:
t1 :33tys rekordów, 49kolumn
t2: 24tys rekordów, 3kolumny

Przy pobieraniu
t1.* -> czas ponad 19sek
t1.id -> 2.5sek (tylko jedno pole z tabeli 1)

Struktura (nie pełna oczywiście) jest w pierwszym poście - oznaczona jako demo.
Moje tabele różnią się tylko ilością rekordów oraz ilością pól.
Być Może coś jeszcze potrzeba - proszę o informację, to dorzucę.

//Edit

i dodam, że samo zapytanie (bez LEFT JOIN'a) wykonuje się 0.0011
później w pętli przeskakuje przez wszystkie rekordy i pobieram tę nieszczęsną kolumnę z tabeli nr 2. Wtedy czas całości wydłuża mi się do ok 8sekund.

Może coś w tej drugiej tabeli mam pochrzanione?
Mam tam 3 kolumny

id
value
id_user

Dodatkowo narzucony jest tam PRIMARY (BTREE) na id oraz value (obie to INT'y)

0

SELECT t1.*, IFNULL(t2.value, 0) as value FROM t1, t2 WHERE t1.id = t2.id_t1 AND YEAR(t1.order_date) = 2023 ORDER BY t1.id DESC

Na takim zapytaniu mi zależy (bo działa bardzo szybko). Niestety nie zwraca 0/null jeśli nie ma powiązania... po prostu pomija te rekordy ;(

3

wpisz EXPLAIN reszta_twojego_zapytania i wklej tu wynik

0

screenshot-20231102195804.png

@abrakadaber
To jest z tym LEFT JOIN (19sek)

3

Panie, MySQL tego co pamiętam, to cuda robi przy LEFT JOIN.
Moje propozycje:

  1. dorzuć index na order_date lub na YEAR(order_date)
  2. dorzuć index na id_table1
    Powinien dostać kopa (na pewno nie będzie używać filesorta)
0

screenshot-20231103085455.png

@Marcin.Miga
Chyba pomogło. Teraz wykonuje się błyskawicznie.
Pytanie - czy to wpłynie w jakikolwiek sposób na inne zapytania? Co dokładnie robi ten index (tak prostym językiem mówiąc)?

0
NewUser2k13 napisał(a):

SELECT t1.*, IFNULL(t2.value, 0) as value FROM t1, t2 WHERE t1.id = t2.id_t1 AND YEAR(t1.order_date) = 2023 ORDER BY t1.id DESC

Na takim zapytaniu mi zależy (bo działa bardzo szybko). Niestety nie zwraca 0/null jeśli nie ma powiązania... po prostu pomija te rekordy ;(

OUTER

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