Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As advised by Sam Dufel, you probably do not need full text search, especially since you are using exact string comparison in your <code>WHERE</code> clauses.</p> <p>Moreover, because of the many-to-many relationship between <code>results</code> and <code>categories</code> (assumed from the <code>HAVING COUNT(c_id) = 3</code> clause), I think in no way can you join both <code>categories</code> and <code>tags</code> in the same query.</p> <p>Without the <code>GROUP BY</code> clause, for one given <code>result</code>, you would get one row for each matching <code>category</code>. For each matching pair (<code>result</code>, <code>category</code>), you would then get one row for each matching <code>tag.name</code>. I don't think there is a way to deal with such a result.</p> <p>What I would suggest is:</p> <p><strong>Step 1</strong>: getting <code>results</code> present in all three categories</p> <pre><code>SELECT results.ID FROM results JOIN categories ON results.id = categories.result_id WHERE categories.name IN ('purchase', 'condo', 'va') GROUP BY results.ID HAVING COUNT(DISTINCT c.c_id) = 3 </code></pre> <p><strong>Step 2</strong>: computing score of any <code>results</code> matching at least one search string</p> <pre><code>SELECT DISTINCT results.*, -- DISTINCT is redundant because of the GROUP BY clause ( 5*(COUNT(tags.result_id)) + -- you actually want to count the number of matches! 1*usefulness + -- warning, see below 10*shares -- warning, see below ) AS score FROM results INNER JOIN tags ON results.id = tags.result_id WHERE tags.name = 'self employed' OR tags.name = 'rental income' OR tags.name = 'commission income' OR tags.name = 'bankruptcy' OR tags.name = 'condo approval' GROUP BY results.ID </code></pre> <p><strong>Step 3</strong>: putting it all together</p> <pre><code>SELECT results.*, ( 5*(COUNT(tags.result_id)) + 1*usefulness + -- warning, see below 10*shares -- warning, see below ) AS score FROM ( SELECT results.id FROM results JOIN categories ON results.id = categories.result_id WHERE categories.name IN ('purchase', 'condo', 'va') AND ( results.scope = 'all' OR results.scope = 'hi' ) AND published = 1 GROUP BY results.id HAVING COUNT(DISTINCT categories.c_id) = 3 ) AS results_subset JOIN results ON results_subset.id = results.id JOIN tags ON results.id = tags.result_id WHERE tags.name = 'self employed' OR tags.name = 'rental income' OR tags.name = 'commission income' OR tags.name = 'bankruptcy' OR tags.name = 'condo approval' GROUP BY results.ID </code></pre> <p>Notice where I chose to include the conditions WHERE on <code>scope</code> and <code>published</code>. This choice is based on the principle that filters should be stated as early as possible. You may get better performance if you place them in the outer query but it really depends on cardinalities.</p> <p>A word of warning: fields <code>usefulness</code> and <code>shares</code> are neither part of the <code>GROUP BY</code> function not included in an aggregation function. This is <a href="http://dev.mysql.com/doc/refman/5.6/en/group-by-extensions.html" rel="nofollow">allowed by MySQL</a> but highly dangerous. If <code>usefulness</code> and <code>shares</code> belong to a table other than <code>result</code> (the table being GROUP'ed BY), the values returned in your query are undefined.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload