Передача результата из одного подзапроса в предложение IN другого подзапроса в MySQL

#mysql #sql

#mysql #sql

Вопрос:

Не уверен, возможно ли это, но если это так, это сделало бы мой запрос намного быстрее.

В принципе, у меня есть запрос, подобный этому:

  SELECT *
   FROM (SELECT bar.id
           FROM pivot_table
          WHERE foo.id = x) t1
   JOIN (SELECT count(*) c1, bar.id
           FROM table
       GROUP BY bar.id) t2 ON t1.id = t2.id
   JOIN (SELECT count(*) c2, bar.id
           FROM another_table
       GROUP BY bar.id) t3 ON t1.id = t3.id
  

Но это довольно медленно, потому что table и another_table огромны. Но на самом деле меня интересуют только те значения, которые являются результатом запроса в t1 . Итак, если бы я мог каким-то образом перенести эти результаты в IN предложение for t2 и t3 , запрос должен был бы значительно ускориться.

Возможно ли это?


Думаю, не слишком понятно. Хорошо, я думал о том, что изменение запроса на что-то вроде:

  SELECT *
   FROM (GROUP_CONCAT (bar.id) as results
                 FROM pivot_table
                WHERE foo.id = x) t1
         JOIN (SELECT count(*) c1, bar.id
                 FROM table
                WHERE bar.id IN (*results from t1*)
                GROUP BY bar.id) t2 ON t1.id = t2.id
         JOIN (SELECT count(*) c2, bar.id
                 FROM another_table
                WHERE bar.id IN (*results from t1*)
                GROUP BY bar.id) t3 ON t1.id = t3.id
  

Может быть быстрее, потому что это сужает количество строк, проверяемых в t2 и t3. Разве это не так?


Все хотят это увидеть, поэтому вот полный запрос:

 SELECT   (k_group.count/jk_group.count) * (s_group.count/jk_group.count) AS ratio,
         jk_group.k_id                                                           ,
         jk_group.s_id
FROM
         -- find the keywords for the job
         (SELECT jk.keyowrd_id AS k_id
         FROM    jobs_keywords jk
         WHERE   job_id = 50100
         )
         extracted_keywords
         -- calculate the necessary values using group_by functions
         INNER JOIN
                  (SELECT  COUNT(*)   count,
                           skill_id   AS s_id ,
                           keyword_id AS k_id
                  FROM     jobs_keywords jk
                           JOIN jobs_skills js
                           ON       js.job_id = jk.job_id
                           JOIN job_feed_details d
                           ON       d.job_id = js.job_id
                  WHERE    d.moderated       = 1
                  GROUP BY skill_id,
                           keyword_id
                  )
                  jk_group
         ON       extracted_keywords.k_id = jk_group.k_id
         INNER JOIN
                  (SELECT  COUNT(*)      count,
                           keyword_id AS k_id
                  FROM     jobs_keywords jk
                           JOIN job_feed_details d
                           ON       d.job_id = js.job_id
                  WHERE    d.moderated       = 1
                  GROUP BY keyword_id
                  )
                  k_group
         ON       jk_group.k_id = k_group.k_id
         INNER JOIN
                  (SELECT  COUNT(*)    count,
                           skill_id AS s_id
                  FROM     jobs_skills js
                           JOIN job_feed_details d
                           ON       d.job_id = js.job_id
                  WHERE    d.moderated       = 1
                  GROUP BY skill_id
                  )
                  s_group
         ON       jk_group.s_id = s_group.s_id
ORDER BY ratio DESC
LIMIT    25
  

Комментарии:

1. Не имеет смысла — зачем использовать агрегированные функции (COUNT), если вы хотите только проверить наличие идентификатора в вспомогательных таблицах? Кстати, тоже много опечаток. Пожалуйста, опубликуйте столбцы (и таблицы, из которых они взяты), которые вы хотите получить в качестве конечного результата.

2. Ваш второй запрос почти идентичен первому запросу, за исключением Group_Concat. Вы могли бы помочь нам, изменив запросы, чтобы они компилировались. Например, foo.id и bar.id в производной таблице T1 не будут работать. Кроме того, это не помогает нам при использовании bar.id в более позднем подзапросе.

3. job_id,keyword_id Является уникальным в job_keywords? job_id, skill_id Является уникальным в job_skills?

4. @thomas для них есть уникальный ключ, да.

Ответ №1:

 SELECT COUNT(t1.id) c1, COUNT(t2.id) c2, COUNT(t3.id) c3, t1.id 
FROM pivot_table t1 
JOIN table t2 ON t1.id=t2.id 
JOIN another_table t3 ON t3.id=t1.id where t1.id=x group by t1.id
  

пожалуйста, убедитесь, что pivot_table.id, table.id и another_table.идентификаторы индексируются

о вашем запросе: проблема вашего запроса в том, что таблица driverd использует буфер соединения, чтобы ускорить ваш запрос, вам следует увеличить размер буфера соединения

Ответ №2:

Я смог выполнить то, что я пытался сделать, вот так:

  SELECT *
   FROM (@var:=GROUP_CONCAT(bar.id) as results
                 FROM pivot_table
                WHERE foo.id = x) t1
         JOIN (SELECT count(*) c1, bar.id
                 FROM table
                WHERE bar.id IN (@var)
                GROUP BY bar.id) t2 ON t1.id = t2.id
         JOIN (SELECT count(*) c2, bar.id
                 FROM another_table
                WHERE bar.id IN (@var)
                GROUP BY bar.id) t3 ON t1.id = t3.id
  

Но преимущества с точки зрения скорости были не слишком значительными. Теперь я отказался от подхода с одним запросом в пользу множества меньших запросов, и это намного лучше.

Ответ №3:

Доработка с учетом фактического запроса

Я думаю, вы можете сократить свой запрос до:

 Select jk.Count( Distinct jk.keyword_id )
        * jk.Count( Distinct js.skill_id )
        / Power( Count(*), 2 )
        As ratio
    , js.skill_id
    , jk.keyword_id
From jobs_keywords As jk
    Join jobs_skills As js
        On js.job_id = jk.job_id
Where jk.job_id =50100
Group By js.skill_id, jk.keyword_id
Order By ratio Desc
Limit 25