Ma requête de travail réelle était une jointure interne, mais cet exemple simple avec jointure croisée semble reproduire presque toujours le problème.
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT NEWID() TEST_ID
) BB ( B )
Avec ma jointure interne, j'avais de nombreuses lignes pour lesquelles j'ai ajouté à chacune un GUID à l'aide de la fonction NEWID (), et pour environ 9 sur 10 de ces lignes, la multiplication avec la table virtuelle à 2 lignes a produit les résultats attendus, seulement 2 copies de le même GUID, tandis que 1 sur 10 produirait des résultats différents. C'était pour le moins inattendu et cela m'a donné beaucoup de mal à essayer de trouver ce bogue dans mon script de génération de données de test.
Si vous regardez les requêtes suivantes en utilisant également les fonctions getdate et sysdatetime non déterministes, vous ne le verrez pas, je ne le vois pas de toute façon - je vois toujours la même valeur datetime dans les deux lignes de résultat final.
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 )
J'utilise actuellement SQL Server 2008 et mon travail pour l'instant consiste à charger mes lignes avec des GUID dans une variable de table avant de terminer mon script de génération de données aléatoires. Une fois que je les ai comme valeurs dans une table par opposition à une table virtuelle, le problème disparaît.
J'ai une solution de contournement, mais je cherche les moyens de contourner ce problème sans tables ni variables de table réelles.
En écrivant ceci, j'ai essayé sans succès ces possibilités: 1) placer le newid () dans une table virtuelle imbriquée:
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT TEST_ID
FROM (
SELECT NEWID() TEST_ID
) TT
) BB ( B )
2) encapsuler le newid () dans une expression cast telle que:
SELECT CAST(NEWID() AS VARCHAR(100)) TEST_ID
3) inverser l'ordre d'apparition des tables virtuelles dans l'expression de jointure
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS JOIN (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
4) Utiliser une application croisée non corrélée
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
Juste avant de poster finalement cette question, maintenant j'ai essayé avec succès, semble-t-il, une croix corrélée s'applique:
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 )
Quelqu'un a-t-il une autre solution de contournement plus élégante et plus simple? Je ne veux vraiment pas utiliser d'application croisée ou de corrélation pour une simple multiplication de lignes si je n'ai pas à le faire.