-4

I need to convert this Eloquent Model Function to a MySQL Query:

public function currentPrice(): HasOne
    {
        return $this->hasOne(Price::class)->ofMany([
            'published_at' => 'max',
            'id'           => 'max',
        ], function(QueryBuilder $query) {
                $query->where('published_at', '<', now());
        });
    }

So, the query should look something like this (missing the above HasOne relation logic that should be in the query):

SELECT items.id, items.article_name, prices.price, prices.published_at, weights.weight, weights.amount
FROM items
INNER JOIN prices ON items.id = prices.item_id
INNER JOIN weights ON items.id = weights.item_id
ORDER BY prices.published_at;
2
  • 1
    Relationship queries are subqueries, not inline queries, so they run after the original query. If you can turn on the general log in mysql and view the log itself (show variables like 'general%'; to see the current settings and log file), then turn on the general log, run the query, turn off the general log, then view the log file to see the queries that it's running.
    – aynber
    Commented Apr 15 at 18:49
  • $this->currentPrice()->toSql() will show you the underlying Eloquent-generated SQL.
    – ceejayoz
    Commented Apr 18 at 19:38

2 Answers 2

0

Db Query is given bellow

SELECT 
    i.id,
    i.article_name,
    p.price,
    p.published_at,
    w.weight,
    w.amount
FROM items i
INNER JOIN (
    SELECT item_id, MAX(published_at) AS max_published_at
    FROM prices
    WHERE published_at < NOW()
    GROUP BY item_id
) latest_prices ON i.id = latest_prices.item_id
INNER JOIN prices p 
    ON p.item_id = latest_prices.item_id 
    AND p.published_at = latest_prices.max_published_at
INNER JOIN weights w ON i.id = w.item_id
ORDER BY p.published_at DESC;
0
-1

Here’s how to express that logic using raw SQL:


SELECT 
    items.id,
    items.article_name,
    prices.price,
    prices.published_at,
    weights.weight,
    weights.amount
FROM items
INNER JOIN (
    SELECT p1.*
    FROM prices p1
    INNER JOIN (
        SELECT item_id, MAX(published_at) AS max_published_at
        FROM prices
        WHERE published_at < NOW()
        GROUP BY item_id
    ) p2 ON p1.item_id = p2.item_id AND p1.published_at = p2.max_published_at
    INNER JOIN (
        SELECT item_id, MAX(id) AS max_id
        FROM prices
        WHERE published_at < NOW()
        GROUP BY item_id
    ) p3 ON p1.item_id = p3.item_id AND p1.id = p3.max_id
) prices ON items.id = prices.item_id
INNER JOIN weights ON items.id = weights.item_id
ORDER BY prices.published_at DESC;
1
  • thank you PriscaEbuka but this query doesn't return the price from the prices table if you have more prices over time for one and the same item_id. The query below from @md-tahmid-farzan works better - I don't understand why but it does. Commented Apr 17 at 5:10

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.