2012-01-21 35 views
2

我想通過連接兩個不同的表來執行更新操作。如何使用兩個表執行更新

My tables are : 

dim_sess 

name          role 
20111012133513aaa123      
20110908072611aaa121   
20111002210235bbb853 
20120113113353bbbl971   

角色列稍後更新。

,另一臺是

employeerole 
username   role    thedate 
aaa   technician  2011-10-12 13:35:13 
aaa   technician  2011-09-08 07:26:11 
bbb   day guard  2011-10-02 21:02:35 
bbb   day guard  2012-01-13 11:33:53 
bbb   night guard  2012-01-13 21:30:00 

我要更新這取決於用戶名和STARTDATE的dim_sess表的作用。同一個用戶可以在不同的日期有不同的角色。兩個表中沒有公共列,唯一要執行連接的列是dim_sess中的「name」。

我編寫了以下查詢來更新dim_ses表。

UPDATE dim_sess 
SET role = (SELECT employeerole.role FROM employeerole 
WHERE SUBSTRING(dim_sess.name,15,7) = employeerole.username 
AND SUBSTRING(dim_sess.name,1,14) = (TEXTCAT(TEXTCAT(TEXTCAT(SUBSTRING(thedate,1,4), SUBSTRING(thedate,6,2)) , TEXTCAT(SUBSTRING(thedate,9,2), SUBSTRING(thedate,12,2))), TEXTCAT(  SUBSTRING(thedate,15,2), SUBSTRING(thedate,18,2))))) 
WHERE SUBSTRING(dim_sess.name,1,21) = (SELECT TEXTCAT((TEXTCAT(TEXTCAT(TEXTCAT(SUBSTRING(thedate,1,4), SUBSTRING(thedate,6,2)) , TEXTCAT(SUBSTRING(thedate,9,2), SUBSTRING(thedate,12,2))), TEXTCAT(SUBSTRING(thedate,15,2), SUBSTRING(thedate,18,2)))) , employeerole.username) AS session FROM employeerole); 

The error message I get is: 
ERROR: more than one row returned by a subquery used as an expression 

既然有兩個表之間沒有共同的專欄中,我嘗試使用子功能相匹配的結果加入其中。但這似乎是一個不好的解決方案。我想知道是否有其他方式來加入這兩個表。

+0

添加一列到dim_sess如姓名 – Matten

回答

0

試試這個:

update DIM_SESS DS 
    set ROLE = 
     (select ER.ROLE 
      from EMPLOYEEROLE ER 
      where substr(
        DS.NAME 
        ,1 
        ,length(to_char(STARTDATE, 'yyyymmddhh24miss') || USERNAME)) like 
        to_char(STARTDATE, 'yyyymmddhh24miss') || USERNAME); 

我在Oracle中測試了這一點,但我想你可能會使用PostgreSQL所以語法可能是一個有點不同。

+0

是的,我正在使用PostgresSQL。我得到了同樣的錯誤:「錯誤:由作爲表達式的子查詢返回的多行」 –

+0

如果您收到該錯誤,則表明您的EMPLOYEEROLE表中有重複條目。嘗試通過USERNAME運行查詢'select USERNAME,STARTDATE,count(*)from EMPLOYEEROLE group,STARTDATE count count(*)> 1;'查找它們。我猜想這種重複不應該被允許,但如果他們是那麼你可以改變我的子查詢爲'select min(ER.ROLE)',例如。 –

0

我看到您的問題唯一的其他解決方案是您的dim_sess表中有一個直接相關的數據字段username。您可以使用持久保存的計算機列,然後在該列上執行JOIN。所以,你的新dim_sess表的定義可能是這樣的:

create table dim_sess 
(
    name varchar(100), 
    username as (SUBSTRING(name,15,7)) persisted, 
    role varchar(100) 
) 
go 
+0

但我也需要startdate.The同一用戶檢查可以在不同的日期不同的角色。 –

+0

@Rohita使用你的'JOIN'。 – 2012-01-21 14:55:57

0

您可以使用employeerole和子查詢從dim_sess.name加上它們的ctid(=唯一行標識符)中提取字段以重新連接到要更新的行來執行相關更新。相關的更新可以通過添加一個FROM子句以及其他表或子查詢來編寫。 另外它有一個regexp_matches函數,它比所有那些substrings()調用更容易。它返回一個數組,其1 - > N元素是捕獲的子字符串。

碼建議:

UPDATE dim_sess d SET role=e.role 
FROM employeerole e, 
(SELECT t[1] as f1, t[2] as f2, t[3] as f3, i from 
(select ctid as i, regexp_matches(name, E'^(\\d{14})([a-z]+)(\\d+)') AS t from dim_sess) s1 
) s2 
WHERE d.ctid=s2.i 
AND to_char(e.thedate,'yyyymmddHH24MISS')=f1 
AND e.username=f2