1

I have an SQL query that looks as follows:

SELECT 
    a.id user_id, a.type, a.email_address, 
    a.name_first, a.name_last, languages.title as language,
    b.created_at purchased_on, b.expires_at watchable_until,
    c.title,
    d.title topic,
    e.title category,
    f.subject, f.grade
FROM users a,
     user_video_purchases b,
     videos c,
     gradesubject_category_topics d,
     gradesubject_categories e,
     gradesubjects f
JOIN languages ON 
          users.language_preferred_id = languages.id
WHERE a.id = b.user_id
      AND b.video_id = c.id
      AND c.gradesubject_category_topic_id = d.id
      AND d.gradesubject_category_id = e.id
      AND e.gradesubject_id = f.id
ORDER BY purchased_on DESC;

This query returns the follow error message:

Unknown column 'users.language_preferred_id' in 'on clause'

The columns exists in the users table and as far as I know the JOIN is correct.

Can someone please point out where I might be going wrong?

Mehravish Temkar
  • 4,275
  • 3
  • 25
  • 44
Marcus Christiansen
  • 3,017
  • 7
  • 49
  • 86
  • 3
    it is not a good habit to mix old-style comma-separated joins and `JOIN` – Radim Bača Oct 19 '18 at 07:16
  • I have yes. Unfortunately does not work. – Marcus Christiansen Oct 19 '18 at 07:16
  • Please stop using comma based Implicit joins and use [Explicit `Join` based syntax](https://stackoverflow.com/questions/44917/explicit-vs-implicit-sql-joins) – Madhur Bhaiya Oct 19 '18 at 07:17
  • @RadimBača I read this on another thread but I'm no too familiar with SQL. Could you elaborate? – Marcus Christiansen Oct 19 '18 at 07:17
  • 2
    Explicit JOIN chains are evaluated before comma separated tables. I.e. your ON clause only has access to gradesubjects and languages columns. Re-write and do explicit JOIN everywhere! – jarlh Oct 19 '18 at 07:18
  • `purchased_on` field is in which table ? – Madhur Bhaiya Oct 19 '18 at 07:23
  • Ah better to see it right? Make your query readable so people will have easier life to answer your question.. – dwir182 Oct 19 '18 at 07:24
  • 1
    a, b and c are lousy table aliases. Chose aliases that make sense, like `u` for `users`, `uvp` for `user_video_purchases` etc. – jarlh Oct 19 '18 at 07:28
  • 1
    Apologies for the lousy query. I was basically just editing another developers query to add another column from another table. I'm glad I'm aware of the syntax changes now for future queries if I come across them again. Thank you for all your help. – Marcus Christiansen Oct 19 '18 at 07:56

3 Answers3

7

You are mixing old school and modern join syntax. You should be using only the latter:

SELECT a.id user_id, a.type, a.email_address, a.name_first, a.name_last,
    l.title as language,
    b.created_at purchased_on,
    b.expires_at watchable_until,
    c.title,
    d.title topic,
    e.title category,
    f.subject, f.grade
FROM users a
INNER JOIN user_video_purchases b
    ON a.id = b.user_id
INNER JOIN videos c
    ON b.video_id = c.id
INNER JOIN gradesubject_category_topics d
    ON c.gradesubject_category_topic_id = d.id
INNER JOIN gradesubject_categories e
    ON d.gradesubject_category_id = e.id
INNER JOIN gradesubjects f
    ON e.gradesubject_id = f.id
INNER JOIN languages l
    ON a.language_preferred_id = l.id
ORDER BY
    purchased_on DESC;
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
4

It is better if you use explicit join like below

SELECT a.id user_id, a.type, a.email_address, a.name_first, a.name_last, languages.title as language,
                                          b.created_at purchased_on, b.expires_at watchable_until,
                                          c.title,
                                          d.title topic,
                                          e.title category,
                                          f.subject, f.grade
                                     FROM users a inner join
                                          user_video_purchases b on a.id = b.user_id
                                          inner join videos c on b.video_id = c.id
                                          inner join gradesubject_category_topics d on c.gradesubject_category_topic_id = d.id
                                          inner join gradesubject_categories e on d.gradesubject_category_id = e.id
                                          inner join gradesubjects f on e.gradesubject_id = f.id
                                          inner JOIN languages l ON a.language_preferred_id = l.id

                                    ORDER BY purchased_on DESC
Fahmi
  • 37,315
  • 5
  • 22
  • 31
2
  • Please stop using comma based Implicit joins and use Explicit Join based syntax
  • Use Proper Aliasing, and once a table has been aliased; you should refer to its column using the Aliasname only.
  • Also, in case of multi-table queries, always refer a column in conjunction with its table name/alias. This will avoid ambiguous behaviour, in case of multiple column(s) having same name(s) across the different tables.

Here is a reworked code using Explicit Joins:

SELECT a.id            AS user_id,
       a.type,
       a.email_address,
       a.name_first,
       a.name_last,
       g.title         AS language,
       b.created_at    AS purchased_on,
       b.expires_at    AS watchable_until,
       c.title,
       d.title         AS topic,
       e.title         AS category,
       f.subject,
       f.grade
FROM   users a
       JOIN user_video_purchases b
         ON a.id = b.user_id
       JOIN videos c
         ON b.video_id = c.id
       JOIN gradesubject_category_topics d
         ON c.gradesubject_category_topic_id = d.id
       JOIN gradesubject_categories e
         ON d.gradesubject_category_id = e.id
       JOIN gradesubjects f
         ON e.gradesubject_id = f.id
       JOIN languages g
         ON a.language_preferred_id = g.id
ORDER  BY purchased_on DESC;  
Madhur Bhaiya
  • 28,155
  • 10
  • 49
  • 57