【问题标题】:SQL: List/aggregate all items for one corresponding transaction idSQL:列出/聚合一个对应事务 id 的所有项目
【发布时间】:2016-12-15 07:15:10
【问题描述】:

我在 vertica db 中有下表:

+-----+------+
| Tid | Item |
+-----+------+
|   1 | A    |
|   1 | B    |
|   1 | C    |
|   2 | B    |
|   2 | D    |
+-----+------+

我想得到这张桌子:

+-----+-------+-------+-------+
| Tid | Item1 | Item2 | Item3 |
+-----+-------+-------+-------+
|   1 | A     | B     | C     |
|   2 | B     | D     |       |
+-----+-------+-------+-------+

请记住,我不知道 transaction_id (Tid) 可以拥有的最大项目数,并且每个 Tid 的项目数量不是恒定的。我尝试使用 join 和 where 但无法使其正常工作。感谢您的帮助。

【问题讨论】:

    标签: sql join concatenation aggregate vertica


    【解决方案1】:

    Vertica 中没有 PIVOT 功能。列不能作为查询的一部分动态定义。你必须指定。

    可能还有其他选项,例如使用 UDX 将它们连接到一个聚合中,例如您将在此 Stack Overflow answer 中找到的内容。但这会将它们放在一个字段中。

    唯一的另一种选择是使用 Python 之类的东西在客户端构建枢轴。否则,您必须有一种方法来为您的查询生成列列表。

    对于我的示例,我假设您正在处理一个唯一的 (Tid, Item) 集。您可能需要进行修改以满足您的需求。

    首先,如果您需要支持的项目,您需要确定最大数量:

    with Tid_count as (
        select Tid, count(*) cnt
        from mytable
        group by 1
    ) 
    select max(cnt)
    from Tid_count;
    

    假设您必须支持的最多项目是 4 个,然后您将生成一个 sql 来进行透视:

    with numbered_mytable as (
        select Tid, 
               Item,
               row_number() over (partition by Tid order by Item) rn
        from   mytable
    )
    select Tid,
           MAX(decode(rn,1,Item)) Item1,
           MAX(decode(rn,2,Item)) Item2,
           MAX(decode(rn,3,Item)) Item3,
           MAX(decode(rn,4,Item)) Item4
    from numbered_mytable
    group by 1
    order by 1;
    

    或者,如果您不想生成 SQL,但知道您永远不会拥有超过 X 个项目,您可以创建一个转到 X 的静态表单。

    【讨论】:

    • 这确实有效!非常感谢。快速跟进:你会如何做相反的事情?这里的动机是,能够删除一行并将表转换回来。这是用于关联模式挖掘,但对于您想要模式中的某个项目的情况。这样您就可以删除所有不包括您的商品的交易。
    • 如果我理解正确,对于每个项目,您将必须全部合并。示例:select Tid, Item1 as Item from ... union all select Tid, Item2 from ... union all select Tid, Item3 from ... .
    【解决方案2】:

    你可以试试这个:

    Create table #table(id int,Value varchar(1))
    
    insert into #table 
    select 1,'A'
    union
    select 1,'B'
    union
    select 1,'C'
    union
    select 2,'B'
    union 
    select 2,'D'
    select id,[1] Item1,[2] Item2,[3] Item3 from
    (
    select id,Dense_rank()over(partition by id order by value)Rnak,Value from #table
    )d
    Pivot
    (Min(value) for Rnak in ([1],[2],[3]))p
    
    drop table #table
    

    【讨论】:

    • 您的代码非常适合我的示例。但我的例子只是一个抽象。在实际情况下,我不知道有多少个不同的项目,一个 tid 对应的最大项目数量是多少。
    • Vertica 中没有 PIVOT。这是一个 SQL Server 答案。
    猜你喜欢
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 2018-10-15
    • 1970-01-01
    • 2018-05-01
    • 2021-01-07
    相关资源
    最近更新 更多