Joins (MySQL)

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen
A join is a join is a join - LET OP: Er zijn nog meer soorten joins, zoals cross join, aka Cartesiaans product

Mijn eerste join

select tbl_temp.ean, tbl_root.ean, tbl_root.sku

from tbl_root

join tbl_temp on tbl_temp.ean = tbl_root.EAN

Dubbele sleutel

En zonder woud van haakjes!

select 

    powertools_es.powertool,
    tbl_powertools_brand_kind_type.Kind02_Uppercase

from 

    tbl_powertools_brand_kind_type

join

    powertools_es 

on 

    tbl_powertools_brand_kind_type.Brand = powertools_es.brand

    and

    tbl_powertools_brand_kind_type.Type = powertools_es.type

limit 0,10000

Multiple joins

Uitbreiden van een join met een tweede join, lijkt triviaal te zijn. De laatste join lijkt zelfs niet gerelateerd te hoeven zijn aan de eerste tabel:

select node.nid, node.title, uc_products.model, uc_product_beterenamen.title 
from node

inner join uc_products on node.nid = uc_products.nid

inner join uc_product_beterenamen on uc_products.model = uc_product_beterenamen.sku;

En deze query is vrij eenvoudig om te fietsen naar een update-query:

update node

inner join uc_products on node.nid = uc_products.nid

inner join uc_product_beterenamen on uc_products.model = uc_product_beterenamen.sku

set node.title = uc_product_beterenamen.title;

Carthesiaans product - Cross join

In dit voorbeeld worden alle advertenties gecombineerd met alle zoektermen:

create table tbl_zoekterm_tmp
select

	"Kohlebuersten" as "account",
	"Merken" as "campaign",
	merk02 as "adgroup", 
	concat (zoekterm," ",merk02) as "zoekterm",
	"                 " as modifier,
	null as memo

from tbl_zoekterm
cross join tbl_merknaam;

Carthesiaans product - Onbedoeld

Meestal krijg ik carthesiaanse producten onbedoeld. Hier is een datawarehouse-voorbeeld

select
---
from root
left join tabela on root.sku = tablea.sku
left join tableb on root.sku = tableb.sku
left join tabelc on root.sku = tablec.sku

Als bv. root en tabela een 1-op-veel-relatie hebben, dan krijg je een cartetisch product, ook al staat er nog tien keer left join.


Left joins & precedence

Het maakt uit of je in het ON-gedeelte het ene veld eerst doet, of het andere veld eerst. Deze twee queries geven verschillende resultaten:

Query 1

-- ================================================================
-- Verbeterde ProductType-query
-- ================================================================
-- * Meeste inner joins vervangen door left joins
-- * 3.304 records. Moet 3.242 zijn

-- SELECT DISTINCT 
-- 
-- 	n.nid AS nid, 
-- 	n.type AS type, 
-- 	n.title AS title, 
-- 	n.created AS created, 
-- 	n.changed AS changed, 
-- 	n.status AS status, 
-- 	ucp.model AS model, 
-- 	ucp.sell_price AS sell_price, 
--  	url_alias.dst AS dst, 
--  	node_revisions.teaser AS teaser, 
--  	node_revisions.body AS body, 
--  	files.filename AS filename, 
-- 	n.uid AS uid
-- 
-- FROM node n
-- INNER JOIN uc_products ucp 						ON n.nid = ucp.nid AND n.vid = ucp.vid
-- left join url_alias url_alias 					ON n.nid = url_alias.nid
-- left join node_revisions node_revisions 				ON n.vid = node_revisions.vid
-- left join content_field_image_cache content_field_image_cache 	ON content_field_image_cache.vid = n.vid
-- left join files files 						ON files.fid = content_field_image_cache.field_image_cache_fid
-- WHERE  (n.type = 'product') 

Query 2

-- ================================================================
-- Left outer joins → Left joins + volgorde ON-velden aangepast
-- ================================================================
-- Aantal records: 3.242 (correct)
--
SELECT DISTINCT 

	n.nid AS nid, 
	n.type AS type, 
	n.title AS title, 
	n.created AS created, 
	n.changed AS changed, 
	n.status AS status, 
-- 	ucp.model AS model, 
-- 	ucp.sell_price AS sell_price, 
-- 	url_alias.dst AS dst, 
-- 	node_revisions.teaser AS teaser, 
-- 	node_revisions.body AS body, 
-- 	files.filename AS filename, 
	n.uid AS uid

FROM node n


left join uc_products ucp 					ON n.nid = ucp.nid AND n.vid = ucp.vid	-- Ziet er ok uit
LEFT JOIN url_alias url_alias 					ON n.nid = url_alias.nid
LEFT JOIN node_revisions node_revisions 			ON n.vid = node_revisions.vid
LEFT JOIN content_field_image_cache content_field_image_cache 	ON n.vid = content_field_image_cache.vid
LEFT JOIN files files 						ON content_field_image_cache.field_image_cache_fid = files.fid -- Deze veroorzaakt het probleem

WHERE  (n.type = 'product');

Records die juist niet overeenkomen

Casus

Ik heb mbv. 'ignore' een tabel gevuld. 64 Records werden overgeslagen ivm. een constraint violation. Nu wil ik weten welke records dat zijn

Oplossing

In de afbeelding aan het begin van dit artikel, is dit de situatie rechts-in-het-midden:

select <...>
from table_a
right join table_b
on a.key = b.key
where a.key is null

Implementatie

-- * brush_tool -	32.931 records
-- * brush_tool_tmp - 	35.901 records
-- * Verschil:           2.700 records → Die wil ik selecteren!

select brush_tool_tmp.* from brush_tool_tmp -- Als je alleen "*" doet zonder tabelnaam, krijg je een Cartesiaans product
left join brush_tool
on brush_tool_tmp.tool_id = brush_tool.tool_id
where brush_tool.tool_id is null

Bronnen