Мой фактический рабочий запрос был внутренним соединением, но этот простой пример с перекрестным соединением почти всегда воспроизводит проблему.
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT NEWID() TEST_ID
) BB ( B )
С моим внутренним объединением у меня было много строк, для которых я добавил к каждому GUID с помощью функции NEWID (), и примерно для 9 из 10 таких строк умножение с двухстрочной виртуальной таблицей дало ожидаемые результаты, всего 2 копии тот же GUID, в то время как 1 из 10 даст разные результаты. Это было неожиданно, мягко говоря, и мне очень трудно было найти эту ошибку в моем скрипте генерации тестовых данных.
Если вы посмотрите на следующие запросы, используя также недетерминированные функции getdate и sysdatetime, вы не увидите этого, в любом случае, я не вижу - я всегда вижу одно и то же значение datetime в обеих конечных строках результата.
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT GETDATE() TEST_ID
) BB ( B )
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT SYSDATETIME() TEST_ID
) BB ( B )
В настоящее время я использую SQL Server 2008, и сейчас я работаю над тем, чтобы загрузить строки с GUID в переменную таблицы перед завершением сценария генерации случайных данных. Как только я получу их в виде значений в таблице, а не виртуальной таблицы, проблема исчезнет.
У меня есть обходной путь, но я ищу способы обхода без фактических таблиц или табличных переменных.
При написании этого я безуспешно пытался использовать следующие возможности: 1) поместить newid () во вложенную виртуальную таблицу:
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT TEST_ID
FROM (
SELECT NEWID() TEST_ID
) TT
) BB ( B )
2) обертывание newid () в приведенном выражении, таком как:
SELECT CAST(NEWID() AS VARCHAR(100)) TEST_ID
3) изменение порядка появления виртуальных таблиц в выражении соединения
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS JOIN (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
4) с использованием некоррелированного креста
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
Непосредственно перед тем, как наконец опубликовать этот вопрос, теперь я попробовал это с успехом, кажется, применимо коррелированное пересечение:
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT A
FROM (
SELECT 1 UNION ALL
SELECT 2
) TT ( A )
WHERE BB.B IS NOT NULL
) AA ( A )
У кого-нибудь есть другой, более элегантный, более простой обходной путь? Я действительно не хочу использовать перекрестное применение или корреляцию для простого умножения строк, если мне не нужно.