niskaMedlem sedan nov. 20112 inlägg 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 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 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