ACTUALIZACIÓN de filas con los valores de la misma tabla

Tengo una tabla como esta:

+------+-------+
|ID    | value |
+------+-------+
| 1    | 150   |
| 2    |       |
| 3    |       |
| 4    |       |
| 5    | 530   |
| 6    | 950   |
| 7    | 651   |
+-------+------+

Quiero copiar los 3 últimos valores y al final de mi mesa tendrá este aspecto:

+------+-------+
|ID    | value |
+------+-------+
| 1    | 150   |
| 2    | 530   |
| 3    | 950   |
| 4    | 651   |
| 5    | 530   |
| 6    | 950   |
| 7    | 651   |
+-------+------+

Es posible?

InformationsquelleAutor Farhad Irani | 2012-11-22

3 Kommentare

  1. 7

    Utilizar un auto-join:

    UPDATE mytable m
    SET    value = m0.value
    FROM   mytable m0
    WHERE  m.id = (m0.id - 3)   -- define offset
    AND    m.id BETWEEN 2 AND 4 -- define range to be affected
    AND    m.value IS NULL;     -- make sure only NULL values are updated

    Si hay deficiencias en la IDENTIFICACIÓN del espacio, utilice la función de windows row_number() para obtener registros de viajes ID a trabajar. Puedo hacer que en una CTE, porque me voy a la reutilización de la mesa dos veces para un auto-join:

    WITH x AS (
       SELECT *, row_number() OVER (ORDER BY ID) AS rn
       FROM   mytable
       )
    UPDATE mytable m
    SET    value = y.value
    FROM   x
    JOIN   x AS y ON x.rn = (y.rn - 4567)   -- JOIN CTE x AS y with an offset
    WHERE  x.id = m.id                      -- JOIN CTE x to original
    AND    m.id BETWEEN 1235 AND 3455
    AND    m.value IS NULL;

    Necesita PostgreSQL 9.1 o posterior para de datos-modificación del Cte.

    • Usted no necesita PostgreSQL 9.1 o posterior para ejecutar WITH x AS ( SELECT...) UPDATE mytable SET ... FROM x . De datos-modificación del Cte en realidad significa UPDATE INSERT DELETE en el WITH parte. Algo así como WITH x as (DELETE FROM t1 ... RETURNING t1.id) INSERT INTO t2 SELECT x.id FROM x
    • Su declaración es incorrecta, mi respuesta es correcta. Así, el término «datos-modificación del CTE» parece un poco engañoso, ya que el CTE no modifica los datos. La clave de la instrucción en el manual es: The sub-statements in WITH are executed concurrently with each other and with the main query. de cualquier manera, usted necesita PostgreSQL 9.1 para el uso de datos-modificación de comando en conexión directa con una CTE. Considere la posibilidad de esta demo: sqlfiddle.com/#!11/53063/1.
    • Lo siento. Estoy usando tanto 9.2 y 8.4 en la producción y estaba confundido. + I v leer el manual. En «7.8.2. De datos-Modificar Declaraciones CON» siempre hay UPDATE INSERT DELETE en WITH parte, así que pensé es acerca de la modificación de datos en la propia CTE (WITH parte).
  2. 0

    Para un ad-hoc de actualización como esta, probablemente no va a ser un mejor camino que tres simples instrucciones de actualización:

    UPDATE mytable SET value = 530 WHERE id = 2;
    UPDATE mytable SET value = 950 WHERE id = 3;
    UPDATE mytable SET value = 651 WHERE id = 4;

    La pregunta es, ¿es esto una ad-hoc actualización que sólo se aplica a este exacto de los datos, o en caso de una actualización general de la regla que desea implementar para todos los posibles datos de la tabla? Si es así, entonces necesitamos más detalle.

    • no, la consulta tiene más de 10000 filas. Yo no puedo hacerlo de esta manera
    • Así que… necesitamos más información. Usted dijo que desea copiar los 3 últimos valores. Siempre que los valores de las tres últimas filas ordenadas por id? Siempre te copiarlos en las filas con valores vacíos? ¿Cómo cada fila se asignaron a uno de los 3 últimos valores?
    • no, no es 3. en menos de 2000 registros. sí que están ordenados por id. sí, yo soy de copiar en las filas con valores vacíos.
  3. 0

    La rígida 3 aparece dos veces y sería reemplazado por sin embargo el número de filas que desee. Se supone que la última 3 registros en realidad tienen valores. Toma los valores y las aplica en la secuencia para el conjunto de registros con valores nulos.

    update a
      set value = x.value
      from (
    
            select nullRows.id, lastRows.value
    
              from ( select id, value
                           ,(row_number() over(order by id) - 1) % 3 + 1 AS key
                       from ( select id, value
                                from a
                                order by id desc
                                limit 3
                            ) x
                       order by 1
    
                   ) AS lastRows
    
                  ,( select id
                           ,(row_number() over(order by id) - 1) % 3 + 1 AS key
                       from a
                       where value is null
                       order by id
    
                   ) AS nullRows
    
             where lastRows.key = nullRows.key
    
          ) x
    
    where a.id = x.id

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea