webForumDet fria alternativet

Mysql join 2 ggr på samma tabell (wordpress)

2 svar · 696 visningar · startad av niska

niskaMedlem sedan nov. 20112 inlägg
#1

Jag har en vanlig wordpress-installation.

Varje sida i min blogg motsvarar en produkt. Produkten har två priser, beroende på vilken typ det är. Dessa lagrar jag som post meta till sidan. En sida kan alltså exempelvis ha "price_current1" = "12" och "price_current2" = "10". En del sidor har endast ett pris, då lagrar jag endast "price_current1". Dessutom har sida/produkt ett orginalpris, exempelvis "price_org1" = "30" och "price_org2" = "20".

Det jag vill göra är att jag vill ta fram en lista med alla sidor/produkter som har ett pris som är lägre än orginalpris, inklusive prisskillnaden.

Tidigare har jag först selekterat fram detta i två frågor, men det jag undrar är om det är möjligt att göra det i en enda fråga så att samma produkt inte kan dyka upp två gånger.

Mina två frågor (som är nästan likadana) ser i nuläget ut så här:

SELECT posts.*, ROUND(A.meta_value) AS price_current,
ROUND(B.meta_value) AS price_org,
ROUND((A.meta_value / B.meta_value) * 100 - 100) AS price_diff
FROM posts, postmeta A, postmeta B WHERE ID = A.post_id
AND ID = B.post_id AND A.meta_key = 'price_current1' AND
B.meta_key = 'price_org1' AND B.meta_value > A.meta_value
AND post_status = 'publish' AND post_type = 'post' ORDER BY price_org DESC
SELECT posts.*, ROUND(A.meta_value) AS price_current,
ROUND(B.meta_value) AS price_org,
ROUND((A.meta_value / B.meta_value) * 100 - 100) AS price_diff
FROM posts, postmeta A, postmeta B WHERE ID = A.post_id
AND ID = B.post_id AND A.meta_key = 'price_current2' AND
B.meta_key = 'price_org2' AND B.meta_value > A.meta_value
AND post_status = 'publish' AND post_type = 'post' ORDER BY price_org DESC

Problemet jag är är alltså att samma sida/produkt kan dyka upp i båda listorna. Min förhoppning är att det går att göra allt i en enda fråga och slippa få dubletter.

Går det att slå ihop dessa två frågor till en enda fråga? Hur?

aasahMedlem sedan mars 20034 471 inlägg
#2

Om jag ser rätt är enda skillnaden på de två frågorna raderna:

   A.meta_key = 'price_current1' AND -- resp 'price_current2' 
   B.meta_key = 'price_org1' AND  -- resp  'price_org2'

Stämmer det? Och i båda fallen finns det rader i posts?

Då borde följande fungera, med lite bättre joinvillkor dessutom:

SELECT 
   posts.*, 
   IFNULL(ROUND(C1.meta_value), 0) AS price_current1,
   IFNULL(ROUND(O1.meta_value), 0) AS price_org1,
   IFNULL(ROUND((C1.meta_value / O1.meta_value) * 100 - 100), 0) AS price_diff1,
   IFNULL(ROUND(C2.meta_value), 0) AS price_current2,
   IFNULL(ROUND(O2.meta_value), 0) AS price_org2,
   IFNULL(ROUND((C2.meta_value / O2.meta_value) * 100 - 100), 0) AS price_diff2
FROM 
   posts P 
   LEFT JOIN postmeta C1 ON 
      P.ID = C1.post_id  AND   
      C1.meta_key = 'price_current1' 
   LEFT JOIN postmeta O1 On
      P.ID = O1.post_id  AND   
      O1.meta_key = 'price_org1' AND
      O1.meta_value > C1.meta_value 
   LEFT JOIN postmeta C2 ON 
      P.ID = C2.post_id  AND   
      C2.meta_key = 'price_current2' 
   LEFT JOIN postmeta O2 On
      P.ID = O2.post_id  AND   
      O2.meta_key = 'price_org2' AND
      O2.meta_value > C2.meta_value 
WHERE 
   P.post_status = 'publish' AND 
   P.post_type = 'post'
ORDER BY 
   P.price_org DESC

Då får du ut en rad per produkt i posts, medan man har räknat ut jämförelsen om det fanns uppgifter i "1 resp 2"-fallen och annars blir beräkningarna NULL. IFNULL(x, 0) = x om x is not null och 0 annars. Om du hellre vill att kolumnerna blir NULL i det läget kan du ta bort den yttre funktionen [IFNULL(...., 0)].

niskaMedlem sedan nov. 20112 inlägg
#3

Stort tack för svar. Jag löste det precis på ett annat sätt. Det var lättare än vad jag trodde. Det räckte med en OR på rätt ställe :p

SELECT posts.*,
ROUND(A.meta_value) AS price_current,
ROUND(B.meta_value) AS price_org,
ROUND((A.meta_value / B.meta_value) * 100 - 100) AS price_diff
FROM posts, postmeta A, postmeta B
WHERE ID = A.post_id AND ID = B.post_id AND ( ( A.meta_key = 'price_current2'
AND B.meta_key = 'price_org2' ) OR ( A.meta_key = 'price_current1'
AND B.meta_key = 'price_org1' ) )
AND B.meta_value > A.meta_value
AND post_status = 'publish'
AND post_type = 'post'
ORDER BY price_org DESC
135 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)