Sql Oracle:使用筛选器连接分组行

Sql Oracle:使用筛选器连接分组行,sql,oracle,Sql,Oracle,我的数据如下: |ID|Name |LinkType|LinkID | |--|-----|--------|-------| |1 |item1|Task |12345 | |1 |item1|Task |22347 | |1 |item1|Event |21342 | |2 |item2|Task |24533 | |2 |item2|Event |43532 | |2 |item2|Event |457 | 我正在尝试将其转换为

我的数据如下:

|ID|Name |LinkType|LinkID | 
|--|-----|--------|-------|
|1 |item1|Task    |12345  | 
|1 |item1|Task    |22347  | 
|1 |item1|Event   |21342  | 
|2 |item2|Task    |24533  | 
|2 |item2|Event   |43532  | 
|2 |item2|Event   |457    | 
我正在尝试将其转换为以下格式:

|ID|Name |Tasks      |Events   |
|--|-----|-----------|---------|
|1 |item1|12345,22347|21342    | 
|2 |item2|24533      |43532,457|
我有一个正在工作的SQL查询,但我想知道是否有任何方法可以优化它,因为它目前非常缓慢。我的数据集约800k行,具有约600k个唯一ID

SELECT ID
    ,Name
    ,(
        SELECT LISTAGG(Attachments2.LinkID, ',') within
        GROUP (
                ORDER BY Attachments2.LinkID
                ) LinkIDs
        FROM Attachments Attachments2
        WHERE Attachments.ID = Attachments2.ID
            AND LinkType  = 'Task'
        GROUP BY Attachments2.ID
        ) Tasks
    ,(
        SELECT LISTAGG(Attachments3.LinkID, ',') within
        GROUP (
                ORDER BY Attachments3.LinkID
                ) LinkIDs
        FROM Attachments Attachments3
        WHERE Attachments.ID = Attachments3.ID
            AND LinkType = 'Event'
        GROUP BY Attachments3.ID
        ) Events
    
FROM Attachments
GROUP BY ID
    ,Name

我总共有4种不同的链接类型,我需要进行分组,这种方法非常慢。我将在5分钟内获得500个结果,因此获取600k行将花费太多时间。

在聚合函数中查找条件聚合情况:

SELECT
  id,
  name,
  LISTAGG(CASE WHEN linktype = 'Task' THEN linkid END, ',')
          WITHIN GROUP (ORDER BY linkid) AS task_ids,
  LISTAGG(CASE WHEN linktype = 'Event' THEN linkid END, ',')
          WITHIN GROUP (ORDER BY linkid) AS event_ids
FROM attachments
GROUP BY id, name
ORDER BY id, name;

当然,您应该在id linktype上有一个唯一的索引。请确保其顺序正确,即先有项目id,然后是链接类型,以便您可以快速访问项目的数据。另请参阅您请求的“备注”部分中我的其他备注。

在聚合函数中查找条件聚合案例:

SELECT
  id,
  name,
  LISTAGG(CASE WHEN linktype = 'Task' THEN linkid END, ',')
          WITHIN GROUP (ORDER BY linkid) AS task_ids,
  LISTAGG(CASE WHEN linktype = 'Event' THEN linkid END, ',')
          WITHIN GROUP (ORDER BY linkid) AS event_ids
FROM attachments
GROUP BY id, name
ORDER BY id, name;

当然,您应该在id linktype上有一个唯一的索引。请确保其顺序正确,即先有项目id,然后是链接类型,以便您可以快速访问项目的数据。另外,请参阅您请求的评论部分中我的其他评论。

好吧,键/值表是一个麻烦的工具。顺便说一句,ID是一个错误的列名,这表明它标识了一行,而它没有标识。它最好是实体id、项目id之类的东西,表明它只标识实体、项目等等。这个名字看起来多余。如果ID 1始终具有名称“item1”,则该名称应驻留在项表中,或存储为链接类型为“name”的键/值。当然,你应该在id、linktype上有一个唯一的索引。否则访问速度会很慢。列名与这里不完全相同,我只是对它们进行了解释,以使示例更简单。我无法控制结构。我需要的数据结构是为了迁移,所以我需要名称和其他类似的东西,我没有添加到这个示例中,尽管这里看起来是多余的。好吧,使用键/值表很麻烦。顺便说一句,ID是一个错误的列名,这表明它标识了一行,而它没有标识。它最好是实体id、项目id之类的东西,表明它只标识实体、项目等等。这个名字看起来多余。如果ID 1始终具有名称“item1”,则该名称应驻留在项表中,或存储为链接类型为“name”的键/值。当然,你应该在id、linktype上有一个唯一的索引。否则访问速度会很慢。列名与这里不完全相同,我只是对它们进行了解释,以使示例更简单。我无法控制结构。我需要的数据结构是为了迁移,所以我需要名称和其他类似的东西,我没有添加到这个示例中,尽管这里的内容看起来是多余的。我试图找到是否有一种方法可以在LISTAGG中进行筛选,但没有找到这样的示例。我会试试这个,因为它看起来很棒!我试图找到是否有一种在Listag中进行过滤的方法,但没有找到这样的例子。我会试试这个,因为它看起来很棒!