使用子查询更新postgres中的表行

时间:2011-06-06 18:49:03

标签: sql postgresql subquery sql-update

使用postgres 8.4,我的目标是更新现有表:

CREATE TABLE public.dummy
(
  address_id SERIAL,
  addr1 character(40),
  addr2 character(40),
  city character(25),
  state character(2),
  zip character(5),
  customer boolean,
  supplier boolean,
  partner boolean

)
WITH (
  OIDS=FALSE
);

最初我使用insert语句测试了我的查询:

insert into address customer,supplier,partner
SELECT  
    case when cust.addr1 is not null then TRUE else FALSE end customer, 
    case when suppl.addr1 is not null then TRUE else FALSE end supplier,
    case when partn.addr1 is not null then TRUE else FALSE end partner
from (
    SELECT *
        from address) pa
    left outer join cust_original cust
        on (pa.addr1=cust.addr1 and pa.addr2=cust.addr2 and pa.city=cust.city 
            and pa.state=cust.state and substring(cust.zip,1,5) = pa.zip  )
    left outer join supp_original suppl 
        on (pa.addr1=suppl.addr1 and pa.addr2=suppl.addr2 and pa.city=suppl.city 
                and pa.state=suppl.state and pa.zip = substring(suppl.zip,1,5))
    left outer join partner_original partn
        on (pa.addr1=partn.addr1 and pa.addr2=partn.addr2 and pa.city=partn.city
                  and pa.state=partn.state and pa.zip = substring(partn.zip,1,5) )
where pa.address_id = address_id

是Newbie我没有转换为更新语句,即用select语句返回的值更新现有行。 任何帮助都非常感谢。

5 个答案:

答案 0 :(得分:554)

Postgres允许:

UPDATE dummy
SET customer=subquery.customer,
    address=subquery.address,
    partn=subquery.partn
FROM (SELECT address_id, customer, address, partn
      FROM  /* big hairy SQL */ ...) AS subquery
WHERE dummy.address_id=subquery.address_id;

此语法不是标准SQL,但对于此类查询比标准SQL更方便。我相信Oracle(至少)接受类似的东西。

答案 1 :(得分:92)

您正在使用UPDATE FROM语法。

UPDATE 
  table T1  
SET 
  column1 = t2.column1 
FROM 
  table t2 
  INNER JOIN table t3 USING (column2) 
WHERE 
  t1.column2 = t2.column2;

<强>参考

答案 2 :(得分:36)

如果使用连接没有性能提升,那么我更喜欢通用表格表达式(CTE)以提高可读性:

WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
)
UPDATE dummy
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE dummy.address_id = subquery.address_id;

恕我直言,更加现代化。

答案 3 :(得分:21)

有很多更新行的方法。

使用子查询来UPDATE行时,可以使用这些方法中的任何一种。

  1. 方法1 [使用直接表参考]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

说明:table1是我们要更新的表,table2 是表格,我们将从中获取要替换/更新的值。 我们正在使用FROM子句来获取table2的数据。 WHERE 子句将有助于设置正确的数据映射。

  1. 方法2 [使用子查询]
UPDATE
  <table1>
SET
  customer=subquery.customer,
  address=subquery.address,
  partn=subquery.partn
FROM
  (
    SELECT
      address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
  ) AS subquery
WHERE
  dummy.address_id=subquery.address_id;

说明:这里我们在FROM子句中使用子查询, 并给它起别名。这样就可以像桌子一样。

  1. 方法3 [使用多个联接表]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2> as t2
  JOIN <table3> as t3
  ON
    t2.id = t3.id
WHERE
  <table1>.address_id=<table2>.address_i;

说明:有时候我们面对的情况是表联接是如此 获取正确的更新数据很重要。为此,Postgres允许 我们可以在FROM子句中联接多个表。

  1. 方法4 [使用WITH语句]

    • 4.1 [使用简单查询]
WITH subquery AS (
    SELECT
      address_id,
      customer,
      address,
      partn
    FROM
      <table1>;
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;
  • 4.2 [使用具有复杂JOIN的查询]
WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM
      <table1> as t1
    JOIN
      <table2> as t2
    ON
      t1.id = t2.id;
    -- You can build as COMPLEX as this query as per your need.
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;

说明:从Postgres 9.1开始,这个(WITH)概念已经 介绍。使用它,我们可以进行任何复杂的查询并生成 欲望的结果。在这里,我们使用这种方法来更新表。

我希望这会有所帮助。?

答案 4 :(得分:7)

@Mayur “ 4.2 [使用具有复杂JOIN的查询]” 公用表表达式(CTE) 帮了我大忙。

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation

pi = 3.14159

velocity = 220 #kilometers per second

def dtheta(r): #creating a function that gives angular velocity based on distance from galactic center
    dtheta = velocity/r #This function comes from the equation for angular velocity, ω=v/r, and ω = 
    #dtheta/dt, which is what our function represents
    return dtheta


#Creating frames at specific times for a set of distances

velocity = 220 #in km/s or pc/My

frames = 11
tstart = 0 #in units of Million Years
tfinal = 1

Stars= 25 #The number of stars being observed, equally spaced from 2 to 20 parsecs from the galactic center

t = np.linspace(tstart,tfinal,frames)
r = np.linspace(2,20,Stars)

plt.figure(figsize=(12,4))
plt.axes(projection = 'polar')
plt.ylim(0,22)
snapi = plt.plot([t[0]*dtheta(i) for i in r] , r, 'ok', lw=1.5)

plt.ion()   # set interactive mode
plt.show()


for i,snap in enumerate(t):
#     for l in snapi:
#         l.remove()
#         del l
    snapp=[snap*dtheta(k) for k in r] 
    snapi = plt.plot(snapp, r, 'ok', lw=1.5)
    plt.legend()
    plt.gcf().canvas.draw()
    plt.pause(2)

希望这对您有帮助...:D