0

我有这张桌子:

p_id        name      skills
1         Sam       #IT #communication #administration
2         Alex      #French #Trainer 

我想要一个 sql 查询来输出这个

  ID     p_fid   skill
   1      1       IT
   2      1       communication
   3      1       administration 
   4      2       French
   5      2       Trainer

使用 PostgreSQL

非常感谢

4

2 回答 2

1

如果您可以将 MS SQL Server 用作 RDBMS,并且该skills列只包含主题标签和单个空格,则可以将该skills列转换为 XML 字符串,然后使用 SQL Server 的内置 XML 操作函数将此字符串拆分为单独的行。

这是适用于您在问题中指定的数据样本的方法。

create table people_skills
(
    p_id int identity(1, 1) primary key clustered,
    name nvarchar(200),
    skills nvarchar(1000)
)

go

insert into people_skills (name, skills) values ('Sam', '#IT #communication #administration')
insert into people_skills (name, skills) values ('Alex', '#French #Trainer')

go

select
    row_number() over (order by ps.p_id) as ID,
    ps.p_id as p_fid,
    cast(x.skill_node.query('text()') as nvarchar(100)) as skill
from
    (
        select
            *,
            -- Assuming that there are no leading and trailing spaces and that all hashtags are separated by single space.
            (cast('<skills>' + (replace(replace(skills, '#', '<skill>'), ' ', '</skill>')) + '</skill></skills>' as xml)) skills_xml
        from
            people_skills
    ) ps
cross apply
    ps.skills_xml.nodes('/skills/skill') as x(skill_node)

如果skills列可以包含除主题标签和空格之外的其他信息,那么您可能需要一种skills比我上面使用的更“智能”的算法来转换为 XML。

于 2012-05-01T17:34:29.047 回答
1

像这样的东西:

CREATE TABLE testbed (p_id int4,name varchar(50),skills text);
INSERT INTO testbed VALUES
    (1,'Sam','#IT #communication #administration'),
    (2,'Alex','#French #Trainer');

SELECT row_number() OVER () AS id,
       p_fid, skill
  FROM (SELECT
        p_id AS p_fid,
        regexp_split_to_table(
             regexp_replace(skills, '^#', ''),
             '[ ]+#') AS skill FROM testbed) AS s;

请查看WindowString 操作Array函数的文档。

如果您确实需要控制技能的位置,则需要更复杂的查询:

WITH arrays AS (
    SELECT p_id,
           regexp_split_to_array(regexp_replace(skills, '^#', ''), '[ ]+#') arr
      FROM testbed
), series AS (
    SELECT p_id, generate_series(1, array_upper(arr, 1)) i
      FROM arrays
)
SELECT row_number() OVER (ORDER BY a.p_id, s.i) AS id,
       a.p_id AS p_fid,
       a.arr[s.i] AS skill
  FROM arrays a
  JOIN series s ON a.p_id = s.p_id
 ORDER BY a.p_id, s.i;
于 2012-05-03T11:54:54.467 回答