{"id":1628,"date":"2024-07-18T12:26:39","date_gmt":"2024-07-18T11:26:39","guid":{"rendered":"https:\/\/editjournal.redakt.eu\/faxmodem\/?p=1628"},"modified":"2024-07-18T12:26:39","modified_gmt":"2024-07-18T11:26:39","slug":"select-case-then-when","status":"publish","type":"post","link":"https:\/\/editjournal.redakt.eu\/faxmodem\/blog\/development\/cakephp\/quick-bites\/select-case-then-when\/","title":{"rendered":"Complex CASE-THEN-WHEN expressions as columns in select queries"},"content":{"rendered":"<p>(Below has been tested on CakePHP 5, but should work on 3+.)<\/p>\n<p>Say you're working on a query that may have to do some currency conversion on the go if user's currency is different from the currency in your database. To make it worse, your site may use a third currency as a base currency (EUR, for example).<\/p>\n<p>A MySQL query that can do this will look like this:<\/p>\n<pre><code>SET @base_currency := &#039;EUR&#039;;\nSET @user_currency := &#039;CHF&#039;;\nSELECT\n    CASE Currencies.code\n        WHEN @user_currency THEN Prices.price\n        WHEN @base_currency THEN Prices.price * CurrenciesUser.exchange_rate\n        ELSE Prices.price \/ Currencies.exchange_rate * CurrenciesUser.exchange_rate\n    END AS &#039;price_converted&#039;\n    \/* all other columns *\/\nFROM\n    prices Prices\n        LEFT JOIN\n    currencies Currencies ON Currencies.id = Pricings.currency_id\n        LEFT JOIN\n    currencies CurrenciesUser ON CurrenciesUser.code = @user_currency\n\/* everything else *\/\nORDER BY price_converted<\/code><\/pre>\n<p>We start by checking if the user currency matches the currency of a given row - if so, we just return the price. Otherwise, we perform the currency conversion.<\/p>\n<p>Here's how that will look written as a CakePHP query:<\/p>\n<pre><code>$user_currency = &#039;CHF&#039;;\n$base_currency = &#039;EUR&#039;;\n$query = $pricesTable-&gt;find(&#039;all&#039;)\n    -&gt;contain([\n        &#039;Currencies&#039;,\n        \/\/ ...\n    ])\n    -&gt;join([\n        &#039;CurrenciesUser&#039; =&gt; [\n            &#039;type&#039; =&gt; &#039;LEFT&#039;,\n            &#039;table&#039; =&gt; &#039;currencies&#039;,\n            &#039;conditions&#039; =&gt; [\n                &#039;CurrenciesUser.code&#039; =&gt; $user_currency\n            ],\n        ],\n    ])\n;\n$query\n    -&gt;selectAlso([\n        &#039;price_converted&#039; =&gt; $query-&gt;newExpr()-&gt;case(&#039;Currencies.code&#039;)\n            -&gt;when($user_currency)\n                -&gt;then($query-&gt;newExpr(&#039;Prices.price&#039;))\n            -&gt;when($base_currency)\n                -&gt;then($query-&gt;newExpr(&#039;Prices.price*CurrenciesUser.exchange_rate&#039;))\n            -&gt;else($query-&gt;newExpr(&#039;Prices.price\/Currencies.exchange_rate*CurrenciesUser.exchange_rate&#039;)),\n    ])<\/code><\/pre>\n<p>Pay attention to how we use <code>$query-&gt;newExpr<\/code> for column names. If we don't, we will get our expressions as literal strings in the query results.<\/p>\n<p>Sources:<\/p>\n<ul>\n<li><a href=\"https:\/\/book.cakephp.org\/4\/en\/orm\/query-builder.html\">https:\/\/book.cakephp.org\/4\/en\/orm\/query-builder.html<\/a><\/li>\n<li><a href=\"https:\/\/stackoverflow.com\/questions\/49103919\/cakephp-query-with-when-case\">https:\/\/stackoverflow.com\/questions\/49103919\/cakephp-query-with-when-case<\/a><\/li>\n<li><a href=\"https:\/\/mark-story.com\/posts\/view\/improved-case-expression-in-cakephp-4-3\">https:\/\/mark-story.com\/posts\/view\/improved-case-expression-in-cakephp-4-3<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>(Below has been tested on CakePHP 5, but should work on 3+.) Say you&#8217;re working on a query that may have to do some currency conversion on the go if user&#8217;s currency is different from the currency in your database. To make it worse, your site may use a third currency as a base currency&hellip; <a class=\"more-link\" href=\"https:\/\/editjournal.redakt.eu\/faxmodem\/blog\/development\/cakephp\/quick-bites\/select-case-then-when\/\">Continue reading <span class=\"screen-reader-text\">Complex CASE-THEN-WHEN expressions as columns in select queries<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1234],"tags":[1201],"class_list":["post-1628","post","type-post","status-publish","format-standard","hentry","category-quick-bites","tag-cakephp-orm","entry"],"_links":{"self":[{"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/posts\/1628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/comments?post=1628"}],"version-history":[{"count":1,"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/posts\/1628\/revisions"}],"predecessor-version":[{"id":1630,"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/posts\/1628\/revisions\/1630"}],"wp:attachment":[{"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/media?parent=1628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/categories?post=1628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/editjournal.redakt.eu\/faxmodem\/wp-json\/wp\/v2\/tags?post=1628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}