Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a SQL subquery to a join

I have two tables with a 1:n relationship: "content" and "versioned-content-data" (for example, an article entity and all the versions created of that article). I would like to create a view that displays the top version of each "content".

Currently I use this query (with a simple subquery):

SELECT 
   t1.id, 
   t1.title, 
   t1.contenttext,
   t1.fk_idothertable
   t1.version
FROM mytable as t1
WHERE (version = (SELECT MAX(version) AS topversion
                  FROM mytable
                  WHERE (fk_idothertable = t1.fk_idothertable)))

The subquery is actually a query to the same table that extracts the highest version of a specific item. Notice that the versioned items will have the same fk_idothertable.

In SQL Server I tried to create an indexed view of this query but it seems I'm not able since subqueries are not allowed in indexed views. So... here's my question... Can you think of a way to convert this query to some sort of query with JOINs?

It seems like indexed views cannot contain:

  • subqueries
  • common table expressions
  • derived tables
  • HAVING clauses

I'm desperate. Any other ideas are welcome :-)

Thanks a lot!

like image 256
sachaa Avatar asked Mar 02 '09 00:03

sachaa


People also ask

How replace subquery with join in SQL Server?

Example: replacing a subquery with a JOIN The difference between these two approaches is in performance. While the JOIN clause in the second example needs to be executed only once, the subquery in the first example will be executed once per farm. In this case, we only have three farms, so the difference is negligible.

Can subqueries be joined?

Subqueries can be used as an alternative to joins. A subquery is typically nested inside the WHERE clause. Subqueries must always be enclosed within parentheses. The table that's specified in the subquery is typically different than the one in the outer query, but it can be the same.

Why use subqueries instead of joins?

As per my observation like two cases, if a table has less then 100,000 records then the join will work fast. But in the case that a table has more than 100,000 records then a subquery is best result.

Can we join a table with a subquery result?

A subquery can be used with JOIN operation. In the example below, the subquery actually returns a temporary table which is handled by database server in memory. The temporary table from the subquery is given an alias so that we can refer to it in the outer select statement.


2 Answers

This probably won't help if table is already in production but the right way to model this is to make version = 0 the permanent version and always increment the version of OLDER material. So when you insert a new version you would say:

UPDATE thetable SET version = version + 1 WHERE id = :id
INSERT INTO thetable (id, version, title, ...) VALUES (:id, 0, :title, ...)

Then this query would just be

SELECT id, title, ... FROM thetable WHERE version = 0

No subqueries, no MAX aggregation. You always know what the current version is. You never have to select max(version) in order to insert the new record.

like image 81
jmucchiello Avatar answered Oct 06 '22 06:10

jmucchiello


Maybe something like this?

SELECT
  t2.id,
  t2.title,
  t2.contenttext,
  t2.fk_idothertable,
  t2.version
FROM mytable t1, mytable t2
WHERE t1.fk_idothertable == t2.fk_idothertable
GROUP BY t2.fk_idothertable, t2.version
HAVING t2.version=MAX(t1.version)

Just a wild guess...

like image 37
jpalecek Avatar answered Oct 06 '22 06:10

jpalecek