ВСТАВКА нескольких строк из одного результата ВЫБОРА

#mysql #sql #subquery

#mysql #sql #подзапрос

Вопрос:

Я вставляю несколько строк в таблицу, используя результат из подзапроса :

 INSERT INTO `doc-file` (docId, fileId) VALUES
    ((SELECT id FROM documents WHERE slug = :slug LIMIT 1), :file1),
    ((SELECT id FROM documents WHERE slug = :slug LIMIT 1), :file2),
    ((SELECT id FROM documents WHERE slug = :slug LIMIT 1), :file3),
  

Результат подзапроса будет одинаковым для каждой строки, которую я хочу вставить, поэтому его действительно нужно запустить только один раз. Написанный таким образом, не будет ли подзапрос выполняться несколько раз? Есть ли способ запустить этот подзапрос только один раз и при этом повторно использовать его результат в нескольких строках?

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

1. Проверьте план объяснения и измерьте его, если это действительно проблема. Есть вероятность, что: а) Оптимизатор оптимизирует это и эффективно выполнит запрос только один раз. б) Даже с разными параметрами оптимизатор, вероятно, превратит его в один запрос в) Любое другое решение будет, по крайней мере, таким же медленным.

Ответ №1:

Вы можете использовать переменную:

 set @value = (SELECT id FROM documents WHERE slug = :slug LIMIT 1);
INSERT INTO `doc-file` (docId, fileId) VALUES
    (@value, :file1),
    (@value, :file2),
    (@value, :file3),
  

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

1. Спасибо! Я удивлен, что это первый раз, когда я вижу, как кто-то упоминает переменные в SQL; Я почти поверил, что их не существует. Есть ли причина, по которой люди избегают их использования?

2. Они существуют, и они очень полезны, но редко используются вне функций, хранимых процедур и триггеров, поскольку все разработчики стараются упростить задачу. В вашем случае переменная легко решает проблему, так почему бы и нет?

Ответ №2:

Вы можете перекрестно объединить подзапрос и другой подзапрос, получая файлы UNION ALL FROM без SELECT ввода.

 INSERT INTO `doc-file`
            (docId,
             fileId)
            SELECT x.id,
                   y.file
                   FROM (SELECT id
                                FROM documents
                                WHERE slug = :slug
                                LIMIT 1) x
                        CROSS JOIN (SELECT :file1 file
                                    UNION ALL
                                    SELECT :file2 file
                                    UNION ALL
                                    SELECT :file3 file) y;
  

Ответ №3:

вы можете создавать уникальные файлы в отдельной временной таблице и объединять их при условии, например, 1 = 1 Если вы не хотите поддерживать отдельную таблицу, заполняйте отдельные значения в подзапросе, чтобы у вас были отдельные таблицы, пусть указано имена файлов Имена файлов: file1 file2 file3

   INSERT INTO `doc-file` (docId, fileId) VALUES
        ( select a.id,f.fileID 
        (SELECT id FROM documents WHERE slug = :slug LIMIT 1) a 
        inner join filenames f on 1=1 
    ))