【问题标题】:SQL query to split a comma separated column into many-to-many relationships将逗号分隔的列拆分为多对多关系的 SQL 查询
【发布时间】:2014-06-04 14:00:35
【问题描述】:

给了我一个 3Gb 的 csv 文件,我需要将它导入 SQL Server 2012。

我现在有 500 万行的数据在一个暂存表中,看起来像这样(简化)。

Staging表:

+-------------------+------------+---------------+------------+
|       Name        | Thumbnail  |     Tags      | Categories |
+-------------------+------------+---------------+------------+
| History           | thumb1.jpg | history,essay | history    |
| Nutricion Lecture | thumb2.jpg | food,essay    | health     |
+-------------------+------------+---------------+------------+

问题是关于我的临时表中的tagscategories 列。

如何将信息从我的临时表传输到我的实际表,并为每个标签和类别创建一个唯一记录 - 创建所需的许多 -对多关系?

它需要根据现有标签检查每个标签以创建新记录 - 或 - 获取现有标签的 Id

Programs:

+----+-----------+------------+
| id |  Program  | Thumbnail  |
+----+-----------+------------+
|  1 | History   | thumb1.jpg |
|  2 | Nutricion | thumb2.jpg |
+----+-----------+------------+

Tags:

+----+---------+
| Id |   Tag   |
+----+---------+
|  1 | history |
|  2 | essay   |
|  3 | food    |
+----+---------+

(类别表省略,因为它看起来与标签相同)

多对多关系:

Programs_Tags:

+---------+-----+
| program | tag |
+---------+-----+
|       1 |   1 |
|       1 |   2 |
|       2 |   2 |
+---------+-----+

Programs_Categories:

+---------+----------+
| program | category |
+---------+----------+
|       1 |        1 |
|       2 |        2 |
+---------+----------+

我假设这在纯 SQL 中更快,然后为它编写一个工具。

【问题讨论】:

    标签: sql sql-server parsing csv many-to-many


    【解决方案1】:

    我不确定这在 SQL 中是否更快。但是,这是一种方法。

    首先,创建您需要的五个表:

    • 程序
    • 标签
    • 类别
    • 程序标签
    • 节目类别

    具有适当的结构,包括身份 ID 列。

    然后将数据加载到程序中。这很简单,只需适当的选择即可。

    然后创建TagsCategories 表。以下是您将如何加载 Tags 表:

    with cte as (
          select (case when tags like '%,%'
                       then left(tags, charindex(tags, ','))
                       else tags
                  end) as tag,
                 (case when tags like '%,%'
                       then substring(tags, charindex(tags, ',') + 1, len(tags))
                  end) as resttags
          from staging
          where tags is not null and tags <> ''
          union all
          select (case when resttags like '%,%' then left(resttags, charindex(tags, ','))
                       else resttags
                  end) as tag,
                 (case when tags like '%,%'
                       then substring(resttags, charindex(resttags, ',') + 1, len(testtags))
                  end) as resttags
          from cte
          where resttags is not NULL and resttags <> ''
         )
    select distinct tags
    from cte;
    

    (显然这需要insert)。

    Categories 执行相同操作。

    然后使用以下命令加载ProgramTags

    select p.ProgramId, t.TagId
    from staging s join
         Programs p
         on s.<whatever> = p.<whatever> join
         Tags t
         on ','+s.tags+',' like '%,'+t.tag+',%';
    

    第一个join是获取program id。第二个是获取适当的标签。性能不会很好,但对于您需要做的事情可能已经足够了。

    【讨论】:

    • 无法正常工作 ---> 消息 8116,级别 16,状态 1,第 1 行参数数据类型 int 对于子字符串函数的参数 1 无效。消息 207,级别 16,状态 1,第 12 行无效的列名称“标签”。消息 207,级别 16,状态 1,第 15 行无效的列名称“标签”。消息 207,级别 16,状态 1,第 16 行无效的列名称“testtags”。消息 207,级别 16,状态 1,第 16 行列名“testtags”无效。
    • @FrankieYale 。 . .我不知道我在想什么,将第一个参数换成substr()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2019-11-10
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    相关资源
    最近更新 更多