Portál AbcLinuxu, 1. června 2024 08:53


Dotaz: SELECT v spojovacej podmienke

31.8.2021 13:23 julo
SELECT v spojovacej podmienke
Přečteno: 1406×
Odpovědět | Admin
Potrebujem pri spajani tabuliek vybrat najaktualnejsi zaznam.
SELECT ....
FROM table t
INNER JOIN table2 t2 ON ( (t2.id=t.id) AND ( (SELECT t2.label from t2 WHERE (t2.id=t.id) ORDER BY t2.datum DESC LIMIT 1) = t2.label) )
JOIN table3...
Oracle 11g vsak hlasi
Invalid expression JOIN table3
                        *
Oracle sice nepodporuje LIMIT do verzie 12c, ale to vsak irelevantne v tomto pripade, lebo evidentne aj bez toho ma s tym (ten isty) problem.

Teda moja otazka je, ci je takyto SELECT v spojovacej podmienke podporovany.
Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

31.8.2021 14:16 kaaja
Rozbalit Rozbalit vše Re: SELECT v spojovacej podmienke
Odpovědět | | Sbalit | Link | Blokovat | Admin
A nebude lepší si t2 profiltrovat na poslední záznam pro dané pro dané ID a pak připojit?
select ....
from table t
inner join (
  select t2.*, row_number() over( partition by t2.id order by t2.datum DESC ) rn
  from table2 t2
) t2_filtered on t2_filtered.id = t.id and t2_filtered.rn =1
31.8.2021 18:26 j
Rozbalit Rozbalit vše Re: SELECT v spojovacej podmienke
Odpovědět | | Sbalit | Link | Blokovat | Admin
Vyrabis cyklus/potencielne nekonecnou rekurzi, a to se parserum SQL vetsinou moc nelibi. A to nemluvim o tom, jak neuveritelne pomaly by neco takovyho bylo.

Takze viz predchozi, udelej si nejdriv select tech nejnovejsich zaznamu a ten joini. Udelat se to da ruzne. Muzes pouzit trebas inner join select ... , to se jako filtr chova.

---

Dete s tim guuglem dopice!
1.9.2021 07:35 Tomáš
Rozbalit Rozbalit vše Re: SELECT v spojovacej podmienke
Odpovědět | | Sbalit | Link | Blokovat | Admin

Select v kauzuli "on" opravdu mít nemůžete. Do klauzuje "on" se píšou jenom predikáty pro spojení tabulek. Krom toho: co když vybrané "label" je stejné pro více záznamů? Pak by dotaz asi neudělal to co si představujete.

Řešení může být např.

select 
  t.*
  ,t2.*
from table t
join table2 t2 on  t.id=t2.id
join ( select id, max(datum) as max_datum from table2 group by id ) t3 on t3.id = t.id and t3.max_datum = t2.datum

Existuje i výkonější varianta jen s jedním joinem:

select 
  t.id
  ,max(t.value1) keep ( dense_rank first order by datum ) as value1
  ,max(t.value2) keep ( dense_rank first order by datum ) as value2
  ,...
  ,max(t2.valueA) keep ( dense_rank first order by datum ) as valueA
  ,max(t2.valueB) keep ( dense_rank first order by datum ) as valueB
  ,...
from table t
join table2 t2 on  t.id=t2.id
group by
  t.id

Snad je patern jasný. Agregační funkci max v prvním čtení ignoruje. Ta zafunguje jen v případě, že by jste neměl totální uspořádáni ( záznamy se stejným datumem pro jedno id). Podstatné pro seřazení je část s dense_rank first order by ... . Ta určuje řazení, podle kterého vyberete první/poslední záznam.

4.9.2021 03:34 kvr
Rozbalit Rozbalit vše Re: SELECT v spojovacej podmienke
Odpovědět | | Sbalit | Link | Blokovat | Admin
Oracle po ruce nemám, ale v prvé řadě mi přijde nesmysl ta FROM vnořeného SELECT. t2 je prakticky alias na aktuální řádek, jaký má smysl SELECT z daného řádku a defakto porovnání samo se sebou (není-li t2 existující tabulka či alias předchozího SELECT) ?

Takže ta chyba může být dřív, akorát je z toho tak vedle, že spadne až o něco později a postěžuje si na zdánlivě korektní JOIN table3. ... což je tedy otázka, neboť zde je příklad useknutý...

K té první části tedy, jestli mělo být cílem najít nejnovější řádek s daným label, tak bych čekal znovu table2 t2i, například (zcela tam vypadnul label, který ale v původním příklad nedává příliš smysl, neboť by měl být vždycky stejný - chce to vyjasnit cíl, potom se dá dořešit):

SELECT .... FROM table t INNER JOIN table2 t2 ON ( (t2.id = (SELECT t2i.id from table2 t2i WHERE (t2i.id=t.id ) ORDER BY t2i.datum DESC LIMIT 1) ) ) JOIN table3...

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.