您如何 return 数据库中现有 table 中特定行的特定列值?
How do you return a specfic column value of a certain row in an existing table within a database?
问题:
我在 PostgreSQL 9.0 中工作,我很难弄清楚如何解决你想要 return 某行的特定列值用于 CASE WHEN 的情况然后声明。
我想基本上进去设置table的值 A:someRow的someColumn的值,等于table的值 B:行X的列A的值,给定行的值X 的 B 列。(如果需要了解问题,请参阅 "Backround Info" 中的更多详细信息)
这是我想做的(但不知道怎么做):
Update tableA
Set someColumn
CASE WHEN given_info_column = 'tableB: row X's column B value'
THEN (here I want to return row X's column A value, finding row X using the given column B value)
ELSE someColumn END
背景信息:(可选,用于说明)
假设在现有数据库中有一个用户 activity table 和一个设备 table,并且已经存在 activity 执行的字符串您正在使用的代码库:(例如)
User_Activity:
id (int) | user_name (string) | activity_preformed (string) | category (string)
---------|-----------------------|----------------------------------------|------------------
1 | Joe Martinez | checked out iphone: iphone2 | dvc_activity
2 | Jon Shmoe | uploads video from device: (id: 12345) | dvc_activity
3 | Larry David | goes to the bathroom |other_activity
Device:
seq (int)| device_name (string) | device_srl_num (int) | device_status (string)|
---------+-----------------------+----------------------+-----------------------+
1 | iphone1 | 12344 | available
2 | iphone2 | 12345 | checked out
3 | android1 | 23456 | available
你老板给你的任务是创建一份报告,显示一个 table 和所有设备 activity,如下所示:
Device Activity Report
(int) (int) (string) (string) (string) (int) (string)
act_seq |usr_id | usr_name | act_performed | dvc_name | dvc_srl_num | dvc_status
---------+-------+--------------+---------------------------------------+-----------+-------------+------------
1 |1 | Joe Martinez | Checked out iphone: iphone2 | iphone2 | 12345 | checked out
2 |2 | John Shmoe | uploads video from device: (id: 12345)| android1 | 23456 | available
为了这个问题的目的,这必须通过向用户 activity table 添加一个名为 dvc_seq 的新列来完成,这将是设备的外键table。您将通过从用户 activity table 查询并加入两个 User_Activity (dvc_seq) = Device (seq)[=16 来创建临时 table =]
这很好,对于 User_Activity table 中的新条目非常有用,它将记录一个 dvc_seq 链接到相关设备 if activity 涉及设备。
问题是您需要在 User_Activity table 中的新 dvc_seq 列中为所有先前与设备相关的条目填写值。由于以前的程序员决定在某些时候使用序列号在 activity_performed 列中指定哪个设备,而其他时候使用设备名称,这会带来一个有趣的问题,您需要从设备中导出关联的设备序列号, 给出其名称或序列号。
所以再一次,我想做的是:(使用这个例子)
UPDATE User_Activity
SET dvc_seq
CASE WHEN activity_performed LIKE 'checked out iphone:%'
THEN (seq column of Device table)
WHERE (SELECT 1 FROM Device WHERE device_name = (substring in place of the %))
ELSE dvc_seq (I think this would be null since there would be nothing here yet)
END
你们谁能帮我完成这个吗??预先感谢所有回复和建议!
在 postgresql 中你不能做像
这样复杂的 CASE 表达式
CASE WHEN activity_performed LIKE 'checked out iphone:%'
仅
CASE WHEN 1, 2
您最多只能创建一个函数
UPDATE User_Activity
SET dvc_seq = getDeviceID(User_Activity.activity_preformed);
在这里你可以更容易地做 IF,CASE
CREATE OR REPLACE FUNCTION getDeviceID(activity text)
RETURNS integer AS
$BODY$
DECLARE
device_name text;
device_id integer;
BEGIN
-- parse the string activity
/* this part is pseudo code
set device_id;
IF (device_id is null)
set device_name;
search for device_id using device_name;
set device_id;
*/
RETURN device_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION get_box(text)
OWNER TO postgres;
当序列号或名称包含在 activity_performed
中时,下面的查询使用更新连接来更新序列号
UPDATE UserActivity
SET a.dvc_seq = b.seq
FROM UserActivity AS a
JOIN devices b
ON UserActivity.activity_performed LIKE '%from device: (id: ' || b.serial_num || '%'
OR UserActivity.activity_performed LIKE '%: ' || b.name || '%'
只是关于如何根据@FuzzyTree 给出的正确答案加速此代码的额外更新(这只适用于具有标准长度的序列号,而不适用于可能的设备名称有很多不同的尺寸)
由于连接中使用了 LIKE,查询对于大型数据库运行速度非常慢。一个更好的解决方案是利用 postgres substring()
和 position()
函数并在序列号上连接表,如下所示:
UPDATE UserActivity
SET a.dvc_seq = b.seq
FROM UserActivity AS a
JOIN devices b
ON b.serial_num =
substring(activity_performed from position('%from device: (id: ' in activity_performed)+(length of the string before the plus so that position returns the start position for the serial number)) for (lengthOfSerialNumberHere))
WHERE UserActivity.activity_performed LIKE '%from device: (id: ' || b.serial_num || '%';`
问题:
我在 PostgreSQL 9.0 中工作,我很难弄清楚如何解决你想要 return 某行的特定列值用于 CASE WHEN 的情况然后声明。
我想基本上进去设置table的值 A:someRow的someColumn的值,等于table的值 B:行X的列A的值,给定行的值X 的 B 列。(如果需要了解问题,请参阅 "Backround Info" 中的更多详细信息)
这是我想做的(但不知道怎么做):
Update tableA
Set someColumn
CASE WHEN given_info_column = 'tableB: row X's column B value'
THEN (here I want to return row X's column A value, finding row X using the given column B value)
ELSE someColumn END
背景信息:(可选,用于说明)
假设在现有数据库中有一个用户 activity table 和一个设备 table,并且已经存在 activity 执行的字符串您正在使用的代码库:(例如)
User_Activity:
id (int) | user_name (string) | activity_preformed (string) | category (string)
---------|-----------------------|----------------------------------------|------------------
1 | Joe Martinez | checked out iphone: iphone2 | dvc_activity
2 | Jon Shmoe | uploads video from device: (id: 12345) | dvc_activity
3 | Larry David | goes to the bathroom |other_activity
Device:
seq (int)| device_name (string) | device_srl_num (int) | device_status (string)|
---------+-----------------------+----------------------+-----------------------+
1 | iphone1 | 12344 | available
2 | iphone2 | 12345 | checked out
3 | android1 | 23456 | available
你老板给你的任务是创建一份报告,显示一个 table 和所有设备 activity,如下所示:
Device Activity Report
(int) (int) (string) (string) (string) (int) (string)
act_seq |usr_id | usr_name | act_performed | dvc_name | dvc_srl_num | dvc_status
---------+-------+--------------+---------------------------------------+-----------+-------------+------------
1 |1 | Joe Martinez | Checked out iphone: iphone2 | iphone2 | 12345 | checked out
2 |2 | John Shmoe | uploads video from device: (id: 12345)| android1 | 23456 | available
为了这个问题的目的,这必须通过向用户 activity table 添加一个名为 dvc_seq 的新列来完成,这将是设备的外键table。您将通过从用户 activity table 查询并加入两个 User_Activity (dvc_seq) = Device (seq)[=16 来创建临时 table =]
这很好,对于 User_Activity table 中的新条目非常有用,它将记录一个 dvc_seq 链接到相关设备 if activity 涉及设备。
问题是您需要在 User_Activity table 中的新 dvc_seq 列中为所有先前与设备相关的条目填写值。由于以前的程序员决定在某些时候使用序列号在 activity_performed 列中指定哪个设备,而其他时候使用设备名称,这会带来一个有趣的问题,您需要从设备中导出关联的设备序列号, 给出其名称或序列号。
所以再一次,我想做的是:(使用这个例子)
UPDATE User_Activity
SET dvc_seq
CASE WHEN activity_performed LIKE 'checked out iphone:%'
THEN (seq column of Device table)
WHERE (SELECT 1 FROM Device WHERE device_name = (substring in place of the %))
ELSE dvc_seq (I think this would be null since there would be nothing here yet)
END
你们谁能帮我完成这个吗??预先感谢所有回复和建议!
在 postgresql 中你不能做像
这样复杂的 CASE 表达式CASE WHEN activity_performed LIKE 'checked out iphone:%'
仅
CASE WHEN 1, 2
您最多只能创建一个函数
UPDATE User_Activity
SET dvc_seq = getDeviceID(User_Activity.activity_preformed);
在这里你可以更容易地做 IF,CASE
CREATE OR REPLACE FUNCTION getDeviceID(activity text)
RETURNS integer AS
$BODY$
DECLARE
device_name text;
device_id integer;
BEGIN
-- parse the string activity
/* this part is pseudo code
set device_id;
IF (device_id is null)
set device_name;
search for device_id using device_name;
set device_id;
*/
RETURN device_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION get_box(text)
OWNER TO postgres;
当序列号或名称包含在 activity_performed
中时,下面的查询使用更新连接来更新序列号UPDATE UserActivity
SET a.dvc_seq = b.seq
FROM UserActivity AS a
JOIN devices b
ON UserActivity.activity_performed LIKE '%from device: (id: ' || b.serial_num || '%'
OR UserActivity.activity_performed LIKE '%: ' || b.name || '%'
只是关于如何根据@FuzzyTree 给出的正确答案加速此代码的额外更新(这只适用于具有标准长度的序列号,而不适用于可能的设备名称有很多不同的尺寸)
由于连接中使用了 LIKE,查询对于大型数据库运行速度非常慢。一个更好的解决方案是利用 postgres substring()
和 position()
函数并在序列号上连接表,如下所示:
UPDATE UserActivity
SET a.dvc_seq = b.seq
FROM UserActivity AS a
JOIN devices b
ON b.serial_num =
substring(activity_performed from position('%from device: (id: ' in activity_performed)+(length of the string before the plus so that position returns the start position for the serial number)) for (lengthOfSerialNumberHere))
WHERE UserActivity.activity_performed LIKE '%from device: (id: ' || b.serial_num || '%';`