2017-08-18 3 views
1
DE

En répondant à un test i fait face à la question suivante, que je n'ai pas pu résoudre:UPDATE SQL requête utilisant

Compte tenu du tableau suivant Z et requête:

Table Z: 
| Value | 
--------- 
| 1 | 
| 2 | 
| 3 | 
| 4 | 
--------- 

Requête:

UPDATE Z 
    SET VALUE = Y.VALUE + 1 
    FROM Z AS Y 
    WHERE Y.VALUE = Z.VALUE + 1; 

SELECT SUM(VALUE) FROM Z; 

La question demande le résultat de l'exécution de cette requête. La question ne mentionne pas un langage SQL spécifique.

La réponse est 16.

Je ne sais pas comment cette requête peut parvenir à ce résultat. Je n'étais même pas capable d'exécuter cette requête dans un environnement réel, il se plaint d'une erreur de syntaxe proche de "FROM".

1 - Connaissez-vous cette requête? 2 - Comment pourrais-je procéder pour exécuter cette requête?

P.S. J'ai eu du mal à trouver des informations sur la clause FROM dans la requête UPDATE.

+0

votre requête, en l'état, ne fonctionnera pas, même dans Postgres, à cause de la virgule sur l'instruction 'SET' – user2877959

+0

désolé, le point-virgule sur l'instruction SET était une faute de frappe, déjà corrigé, le problème reste –

+0

je vois. En effet, le système ajoute simplement 2 à 1,2,3 puis somme de l'ensemble (3,4,5,4). La partie délicate ici est que la clause where est que la jointure automatique utilise la valeur Y et ensuite en ajouter un – xQbert

Répondre

2

Une base de données où le code fonctionnera est Postgres. Selon RexTester, c'est en effet la réponse.

La raison en est que vous ajoutez "2" à chaque valeur Z correspondante: z = y.value + 1 = z.value + 1 + 1 - mais la quatrième valeur ne correspond pas. Postgres génère les éléments suivants:

value 
1 4 
2 3 
3 4 
4 5 

Il s'agit des mêmes données dans un ordre différent.

Avec une déclaration similaire, SQL Server fait la bonne chose: (. J'utilise la virgule redoutée dans une clause FROM de garder les deux déclarations aussi proches que possible)

UPDATE Z 
    SET val = Y.val + 1 
    FROM Z, Z AS Y 
    WHERE Y.val = Z.val + 1; 

Il retourne :

val 
1 3 
2 4 
3 5 
4 4 

Les deux ensembles de résultats sont identiques, ils sont simplement dans un ordre différent.

+0

Il me semble que Postgres et SQL Server produisent le même résultat. Seulement, dans ce cas, Postgres ne conserve pas la commande d'origine. Dans votre RexTester lié, si vous échangez les valeurs lors de la génération de la première table, le résultat final n'est pas affecté. – user2877959

+0

@ utilisateur2877959. . . Je vous remercie. J'ai corrigé la réponse. J'ai mal interprété la première colonne. Rextester le calcule pour vous - ce n'est pas une colonne dans les données. –

2

J'espère que cela pourrait aider (fait sur MSSQL): Le premier SELECT montrera les valeurs originales que la mise à jour utilisera.

J'ai fait UPDATE à l'intérieur de la transaction/rollback afin qu'il ne change pas la table. Vous pouvez supprimer BEGIN TRAN et ROLLBACK TRAN si vous souhaitez modifier votre tableau de données.

CREATE TABLE TZ (VALUE INT) 
    INSERT INTO TZ VALUES (1),(2),(3),(4) 

    SELECT Z.VALUE AS Z_VALUE, Y.VALUE AS Y_VALUE 
    FROM TZ Z 
    INNER JOIN TZ Y ON Y.VALUE=Z.VALUE +1 
    ; 

    BEGIN TRAN 
    UPDATE Z SET VALUE=Y.VALUE+1 
    FROM TZ Z 
    INNER JOIN TZ Y ON Y.VALUE=Z.VALUE +1 
    ; 
    SELECT * FROM TZ; 
    SElECT SUM(VALUE) AS TOT FROM TZ; 
    ROLLBACK TRAN 

sortie premier SELECT:

Z_VALUE, Y_VALUE 
1  , 2 
2  , 3 
3  , 4 

sortie de SELECT après mise à jour:

VALUE 
3 
4 
5 
4 

Ainsi, la somme est en fait 16

1

Si cela a fonctionné et je ne serais pas Attendez-vous à ce que cela se produise dans chaque base de données, ce qui pourrait aider à illustrer ce qui se passe. Y est juste un alias de Z. Ce tableau représente la jonction des tables au cours de la mise à jour et les résultats finaux:

Z values Y (alias) joined on Z + 1 Update Value Z following update 
======== ========================= ============ ================== 
      1       NO MATCH 
1   2       3    3 
2   3       4    4 
3   4       5    5 
4          NO MATCH  4 
                 (SUM: 16)