Algorytm dopasowywania użytkowników Rails 3 do zapytania SQL (KOMPLIKOWANY)

Obecnie pracuję nad aplikacją, która pasuje do użytkowników na podstawie odpowiedzi na pytania. Zrozumiałem mój algorytm w zwykłych zapytaniach RoR i ActiveRecord, ale nie mogę go używać. Aby dopasować jednego użytkownika do 100 innych użytkowników

Completed 200 OK in 17741ms (Views: 106.1ms | ActiveRecord: 1078.6ms)

na mojej lokalnej maszynie. Ale nadal ... Chcę to teraz zrealizować w surowym SQL, aby uzyskać większą wydajność. Ale naprawdę mam problem z odczytaniem zapytań SQL w zapytaniach SQL i podobnych rzeczach, a także z obliczeniami itp. Moja głowa zaraz wybuchnie i nawet nie wiem, od czego zacząć.

Oto mój algorytm:

def match(user)
  @a_score = (self.actual_score(user).to_f / self.possible_score(user).to_f) * 100
  @b_score = (user.actual_score(self).to_f / user.possible_score(self).to_f) * 100

  if self.common_questions(user) == []
    0.to_f
  else
    match = Math.sqrt(@a_score * @b_score) - (100 / self.common_questions(user).count)
    if match <= 0
      0.to_f
    else
      match
    end
  end
end

def possible_score(user)
  i = 0
  self.user_questions.select("question_id, importance").find_each do |n|
    if user.user_questions.select(:id).find_by_question_id(n.question_id)
      i += Importance.find_by_id(n.importance).value
    end
  end
  return i
end

def actual_score(user)
  i = 0
  self.user_questions.select("question_id, importance").includes(:accepted_answers).find_each do |n|
    @user_answer = user.user_questions.select("answer_id").find_by_question_id(n.question_id)
    unless @user_answer == nil
      if n.accepted_answers.select(:answer_id).find_by_answer_id(@user_answer.answer_id)
        i += Importance.find_by_id(n.importance).value
      end
    end
  end
  return i
end

Zasadniczo użytkownik odpowiada na pytania, wybiera odpowiedzi, które akceptuje i jak ważne jest dla niego to pytanie. Algorytm sprawdza następnie, jakie pytania mają użytkownicy 2, jeśli użytkownik1 dał odpowiedź, użytkownik2 akceptuje, jeśli tak, to dodaje się ważność użytkownika2 dla każdego pytania, która tworzy wynik użytkownika1. Również na odwrót dla użytkownika2. Podzielony przez możliwy wynik daje procent, a oba procenty zastosowane do średniej geometrycznej dają mi jeden całkowity procent dopasowania dla obu użytkowników. Wiem, że dość skomplikowane. Powiedz, czy nie wyjaśniłem tego wystarczająco dobrze. Mam tylko nadzieję, że mogę to wyrazić w surowym SQL. Wydajność to wszystko.

Oto moje tabele bazy danych:

CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "username" varchar(255) DEFAULT '' NOT NULL); (left some unimportant stuff out, it's all there in the databse dump i uploaded)

CREATE TABLE "user_questions" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer, "question_id" integer, "answer_id" integer(255), "importance" integer, "explanation" text, "private" boolean DEFAULT 'f', "created_at" datetime);

CREATE TABLE "accepted_answers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "user_question_id" integer, "answer_id" integer);

Myślę, że szczyt zapytania SQL musi wyglądać mniej więcej tak?

SELECT u1.id AS user1, u2.id AS user2, COALESCE(SQRT( (100.0*actual_score/possible_score) * (100.0*actual_score/possible_score) ), 0) AS match
FROM 

Ale ponieważ nie jestem mistrzem SQL i mogę wykonywać zwykłe rzeczy, które moja głowa ma eksplodować. Mam nadzieję, że ktoś pomoże mi to zrozumieć. Albo przynajmniej popraw moje wyniki w jakiś sposób! Dzięki wielkie!

EDYTOWAĆ:

W oparciu o odpowiedź Kreatora udało mi się uzyskać ładną instrukcję SQL dla „possible_score”

SELECT SUM(value) AS sum_id 
FROM user_questions AS uq1
INNER JOIN importances ON importances.id = uq1.importance
INNER JOIN user_questions uq2 ON uq1.question_id = uq2.question_id AND uq2.user_id = 101
WHERE uq1.user_id = 1

Próbowałem pobrać „actual_score”, ale to nie zadziałało. Mój menedżer bazy danych uległ awarii podczas wykonywania tego.

SELECT SUM(imp.value) AS sum_id 
FROM user_questions AS uq1
INNER JOIN importances imp ON imp.id = uq1.importance
INNER JOIN user_questions uq2 ON uq2.question_id = uq1.question_id AND uq2.user_id = 101
INNER JOIN accepted_answers as ON as.user_question_id =  uq1.id AND as.answer_id = uq2.answer_id
WHERE uq1.user_id = 1
EDIT2

Dobra, jestem idiotą! Nie mogę oczywiście użyć „as” jako aliasu. Zmieniono to na aa i zadziałało! W00T!

questionAnswers(2)

yourAnswerToTheQuestion