J'essaie d'insérer au hasard des valeurs d'une liste de valeurs prédéfinies dans une table pour les tests. J'ai essayé d'utiliser la solution trouvée sur cette question Stackoverflow Question:
stackoverflow.com /.../ update-sql-table-with-Value-Valeur-de-Autre-table code> p>
Quand II a essayé ceci, tous Mes valeurs "aléatoires" insérées sont exactement les mêmes pour tous les 3000 enregistrements. P>
Lorsque j'exécute la partie de la requête qui sélectionne réellement la ligne aléatoire, elle sélectionne un enregistrement aléatoire à chaque fois que je l'exécute à la main, alors je connais que la requête fonctionne. Mes meilleures suppositions quant à ce qui se passe sont: p>
SELECT CODE> d'une manière ou d'une autre, ne permettant pas à la sous-requête d'être évaluée plus d'une fois li>
- La graine de la valeur aléatoire est la même sur chaque enregistrement. Les mises à jour de la requête LI>
ul>
Je suis coincé sur ce que sont mes options. Est-ce que je fais quelque chose de mal ou y a-t-il une autre façon que je devrais faire ça? P>
Ceci est le code que j'utilise: p> xxx pré> p>
6 Réponses :
Je n'ai pas le temps de vérifier cela maintenant, mais mon intestin me dit que si vous deviez créer une fonction sur le serveur pour obtenir la valeur aléatoire qu'elle ne l'optimiserait pas.
alors vous le feriez avoir p>
Il n'y a pas d'optimisation ici.
Votre utilisation d'une sous-requête qui sélectionne une seule valeur, il n'y a rien à optimiser. P>
Vous pouvez également essayer de mettre une colonne du tableau de votre mise à jour la sélection et voir si cela change quelque chose. Qui peut déclencher une évaluation pour chaque ligne de MyTable P>
Utilisez une jointure croisée pour générer des données aléatoires p>
Avez-vous un exemple que je pourrais utiliser? Je ne connais pas l'idée de jointures croisées.
Je suis venu avec une solution qui est un peu de hack et très inefficace (10 ~ secondes pour mettre à jour 3000 enregistrements). Parce que cela est utilisé pour générer des données de test, je ne dois pas être préoccupé par la rapidité, cependant.
Dans cette solution, j'ai itérus sur toutes les rangées de la table et mettez à jour les valeurs une ligne à la fois. Il semble fonctionner: p>
J'ai eu une pièce de théâtre avec cela et j'ai trouvé un moyen plutôt hacrain de le faire avec l'utilisation d'une variable de table intermédiaire.
Une fois que @Randomstuff est configuré, nous le faisons (note dans mon cas, @ MyTable est une variable de table, ajustez en conséquence pour votre table normale): p> Ainsi, nous avons une table intermédiaire avec chaque combinaison de (identifiant MyTable, valeur aléatoire) et une valeur de tri aléatoire pour chaque ligne spécifique à cette combinaison. Puis p> Il s'agit d'une vieille astuce qui supprime toutes les lignes pour une myTable donnée.Id à l'exception de celle avec la valeur de tri inférieure - Joignez-vous à la table de la valeur est plus petit et supprimez-le où un tel rejoindre a réussi. Cela laisse juste derrière la valeur la plus basse. Donc, pour chaque myTable.Id, nous avons juste une valeur (aléatoire) à gauche .. Ensuite, nous venons de le brancher dans la table: p> et vous avez terminé! < / p> i dit em> c'était hacky ... p> p>
Lorsque le moteur de requête voit ceci ... ... C'est tout comme ", Ooooh, une sous-requête scalaire maigre, je vais mettre en cache ça!" P> Vous devez tromper le moteur de requête dans la pensée qu'elle est non capable. Réponse était proche, mais le moteur de requête était assez intelligent pour voir la tautalogie de mytable.mycolumn = myTable.mycolumn code>, mais ce n'est pas assez intelligent pour voir à travers cela. P> UPDATE MyTable
SET MyColumn = (SELECT TOP 1 val
FROM @randomStuff r
INNER JOIN MyTable _MT
ON M.Id = _MT.Id
ORDER BY NEWID())
FROM MyTable M
OK, je ne me souviens pas si vous pouvez faire la jointure intérieure comme celle-là dans SQL Server 2000, mais que j'ai utilisé tout le temps avant de partir en 2005. C'était il y a trop d'années pour que je me souvienne, bien que. Mais cela devrait fonctionner en 2005 et plus tard très bien.
+1 Ceci est fantastique, hower il y a un petit typo, sur mt.id = _mt.id code> doit être sur m.id = _mt.id code>
Comme suggéré par @rippo, la requête complète doit être: Mise à jour M Set MyColumn = (Sélectionnez le top 1 Val de @Randomstuff interne Rejoignez MyTable _MT sur m.Id = _mt.Id Commande par NewID ()) de MyTable M MyTABLE M MyTable m < / code>. J'ai également remarqué que r code> n'est pas utilisé et modifié en Mettre à jour M code> au lieu de Mise à jour MyTable code>. +1 pour les curseurs non aussi amusants
Cette question / réponse peut être utile: Stackoverflow.com/a/9039661/47226