* Привет всем, я работаю над запросом и не уверен, как сделать так, чтобы он обрабатывался как можно быстрее и с минимальной избыточностью, насколько это возможно. Я действительно надеюсь, что кто-то там может помочь мне придумать хороший способ сделать это.
Заранее спасибо за помощь! *
Хорошо, вот то, что у меня есть, как я могу объяснить. Я упростил таблицы и математику, чтобы просто понять то, что я пытаюсь понять.
По сути, у меня небольшая таблица, которая никогда не меняется и всегда будет содержать только 50 тыс. Записей:
Values_Table
ID Value1 Value2
1 2 7
2 2 7.2
3 3 7.5
4 33 10
….50000 44 17.2
И пара таблиц, которые постоянно меняются и являются довольно большими, например, с потенциалом до 5 миллионов записей:
Flags_Table
Index Flag1 Type
1 0 0
2 0 1
3 1 0
4 1 1
….5,000,000 1 1
Users_Table
Index Name ASSOCIATED_ID
1 John 1
2 John 1
3 Paul 3
4 Paul 3
….5,000,000 Richard 2
Мне нужно связать все 3 таблицы вместе. Большинство результатов, которые, вероятно, когда-либо будут возвращены из небольшого стола, находятся где-то около 100 результатов. Большие таблицы объединяются в индексе, а затем они соединяются с Values_Table ON Values_Table.ID = Users_Table.ASSOCIATED_ID…. Эта часть достаточно проста.
Для меня становится сложным то, что мне нужно как можно быстрее вернуть список, ограниченный 10 результатами, где математически оперируются value1 и value2, чтобы вернуть new_ value, где new_value меньше 10 и результат сортируется по этому new_value и любым другим, где нужные мне заявления могут быть применены к флагам. Мне нужно уметь двигаться по пределу. EG LIMIT 0,10 / 11,10 / 21,10 и т.д ...
В последующем (или таком же, если возможно) запросе мне нужно получить 10 лучших счетчиков всех типов, которые соответствовали этому критерию до применения ограничения.
Так, например, я хочу присоединиться ко всем этим и вернуть что-нибудь, где Value1 + Value2 <10 И мне также нужно количество. </p>
Итак, что я хочу:
Index Name Flag1 New_Value
1 John 0 9
2 John 0 9
5000000 Richard 1 9.2
Второй ответ будет:
ID (not index) Count
1 2
2 1
Я попробовал это несколькими способами и в итоге придумал следующий довольно уродливый запрос:
SELECT INDEX, NAME, Flag1, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10
ORDER BY New_Value
LIMIT 0,10
А затем для подсчета:
SELECT ID, COUNT(TYPE) as Count, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10
GROUP BY TYPE
ORDER BY New_Value
LIMIT 0,10
Важно иметь возможность фильтровать различные флаги и тому подобное в моем предложении WHERE; комментировать это может показаться глупым, но я упоминаю об этом, потому что из того, что я увидел, можно было бы быстрее использовать оператор HAVING, но я не верю, что в некоторых случаях это сработает, в зависимости от того, что я хочу использовать в предложении WHERE. фильтровать против.
А при фильтрации с использованием таблицы флагов:
SELECT INDEX, NAME, Flag1, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10 AND Flag1 = 0
ORDER BY New_Value
LIMIT 0,10
... отфильтрованный счет:
SELECT ID, COUNT(TYPE) as Count, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10 AND Flag1 = 0
GROUP BY TYPE
ORDER BY New_Value
LIMIT 0,10
Это прекрасно работает, но приходится выполнять математику несколько раз для каждой строки, и у меня возникает неприятное ощущение, что она также выполняет математику несколько раз в одной и той же строке таблицы Values_table. Я думал, что сначала я должен получить только действительные ответы из Values_table, а затем соединить их с другими таблицами, чтобы сократить обработку; с тем, как SQL оптимизирует вещи, хотя я не был уверен, может ли он этого не делать. Я знаю, что мог бы использовать предложение HAVING, чтобы выполнить математику только один раз, если бы я делал это таким образом, но я не уверен, как бы я тогда лучше всего к этому присоединился.
Мои вопросы:
- Могу ли я избежать выполнения этой математики дважды и при этом заставить запрос работать
(или я полагаю, если есть хороший способ
чтобы первый тоже работал
это было бы здорово)
- Какой самый быстрый способ сделать это
как это то, что будет
бегать очень часто.
Кажется, это должно быть до боли просто, но я просто упускаю что-то глупое.
Я думал о том, чтобы потянуть за временную таблицу, а затем соединить эту таблицу с самим собой, но похоже, что я обменял бы математику на итерации против таблицы и все еще заканчивал бы медленным.
Спасибо всем за помощь в этом и, пожалуйста, дайте мне знать, если мне нужно что-то прояснить здесь!
** Чтобы уточнить вопрос, я не могу использовать 3-й столбец с предварительно рассчитанными значениями, потому что на самом деле математика гораздо сложнее, чем сложение, я просто упростил ее для иллюстрации.