Sql 如何返回数据库中现有表中某一行的特定列值?
问题: 我在PostgreSQL 9.0中工作,我很难弄清楚如何处理需要返回某行的特定列值以用于CASE WHEN THEN语句的情况 我想基本上进入并设置表A:someRow的someColumn值,等于表B:row X的column A值,给定row X的column B的值。(如果需要了解问题,请参阅“背景信息”中的更多详细信息) 这就是我想做的(但不知道怎么做): 背景信息:(可选,用于澄清) 假设在已经存在的数据库中有一个用户活动表和一个设备表,其中包含已经存在的活动执行字符串,这些字符串一直存在于您正在使用的代码库中:(例如) 老板的任务是创建一个报告,其中显示一个包含所有设备活动的表,如下所示:Sql 如何返回数据库中现有表中某一行的特定列值?,sql,postgresql,foreign-keys,case,case-when,Sql,Postgresql,Foreign Keys,Case,Case When,问题: 我在PostgreSQL 9.0中工作,我很难弄清楚如何处理需要返回某行的特定列值以用于CASE WHEN THEN语句的情况 我想基本上进入并设置表A:someRow的someColumn值,等于表B:row X的column A值,给定row X的column B的值。(如果需要了解问题,请参阅“背景信息”中的更多详细信息) 这就是我想做的(但不知道怎么做): 背景信息:(可选,用于澄清) 假设在已经存在的数据库中有一个用户活动表和一个设备表,其中包含已经存在的活动执行字符串,这些字
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
出于这个问题的目的,必须通过向名为dvc_seq的用户活动表添加一个新列来完成,该列将是设备表的外键。您将通过从用户活动表查询并连接两个where user_activity(dvc_seq)=Device(seq)来创建一个临时表
这很好,对于用户活动表中的新条目非常有用,如果活动涉及设备,用户活动表将记录链接到相关设备的dvc seq
问题是,您需要在User_Activity表中的新dvc_seq列中填入与设备相关的所有以前条目的值。由于之前的程序员决定在activity_performed(活动_执行)列中指定特定时间使用序列号而其他时间使用设备名称的设备,因此这提出了一个有趣的问题,您需要从给定设备名称或序列号的设备中导出关联的设备序列号
再一次,我想做的是:(使用这个例子)
你们谁能帮我完成这个任务??提前感谢所有回复和建议 在postgresql中,您不能像
CASE WHEN activity_performed LIKE 'checked out iphone:%'
只有
您最多只能创建一个函数
UPDATE User_Activity
SET dvc_seq = getDeviceID(User_Activity.activity_preformed);
在这里你可以做,如果情况更容易
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;
当序列号或名称包含在执行的活动中时,下面的查询使用更新联接来更新序列号
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给出的正确答案,只需对如何加速此代码进行额外更新(这只适用于具有标准长度的序列号,而不适用于可能有许多不同大小的设备名称) 由于联接中使用了类似的方法,因此对于大型数据库,查询运行速度非常慢。更好的解决方案是利用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 || '%';`
我不确定我是否想帮你教我的Iphone跟踪我的卫生间休息时间,但是你能用你的数据创建一个新的记录吗?这会有很大帮助。要做到这一点,我们需要知道如何解析您的
活动执行的列。我们是否可以检查char:
的第一次出现,并尝试查看是否有和id
或之后是否有设备名称
?或者,dvc\u name
column可以有空间吗?@JuanCarlosOropeza老实说,我还没有给那个部分太多的空间。dvc\u名称
可以有空格,例如,“android 3”
将是一个有效的条目。肯定要像你说的那样解析那个字符串,但现在我更关心的是如何返回特定行的列值。无论您如何解析它,返回特定行的列值应该是相同的,对吗?如果没有您所拥有的详细示例,我无法帮助您。我只能给你一般的指导方针。如果您需要我回答中的伪代码的帮助,请告诉我。我考虑过这一点,但可能b.serial\u num
和b.name
会出现在a.activity\u执行的
的其他部分,而不是deviceID@JuanCarlosOropeza我添加了一些前缀以降低出错的可能性positives@FuzzyTree谢谢你的帮助,这是我得到的最接近的查询,但仍然给我带来问题。。。测试此查询时,它会更新用户活动表中的每个条目,而不仅仅是Activity_执行的条目看起来像代码中的两个字符串。每个条目也会被相同的dvc序列号填充。有什么想法吗?dvc\u seq
的名称和序列号是什么?它们中有一个是空的吗?更新:我通过在末尾添加一个额外的WHERE子句来实现它,例如:WHERE UserActivity.activity\u的执行方式与设备中的“%from”:(id:“|| b.serial_num | |“%”或UserActivity.activity|u的执行方式类似“%”:“:”| b.name | |“%”
再次感谢@FuzzyTree,我将此答案标记为解决问题的答案。
UPDATE User_Activity
SET dvc_seq = getDeviceID(User_Activity.activity_preformed);
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;
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 || '%'
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 || '%';`