0

假设有一个简单的表:

CREATE TABLE [dbo].[foo](
    [foo_id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
        [val1_id] [int] NULL,
        [val1_amount] [int] NULL,
        [val2_id] [int] NULL,
        [val2_amount] [int] NULL,
        [val3_id] [int] NULL,
        [val3_amount] [int] NULL,
        [val4_id] [int] NULL
        [val4_amount] [int] NULL,
) ON [PRIMARY]

还有一些其他的表是:

CREATE TABLE [dbo].[val](
    [val_id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
        [amount] [int] NOT NULL,
) ON [PRIMARY]

应用程序的用户将从表 val 中选择一个条目,应用程序将以非确定性的方式将 val_id 和 amount 放入 val?_id 和 val?_amount 中(是的,我知道这不好,但我有来处理它)。

鉴于 val_id/amount 可以存储在任何 val?_id/val?_amount 列中,有没有一种方法可以生成输出,该输出将按 foo 表中的 val_id 和 SUM foo 表中的金额值进行分组?注意,如果 val_id 存储在 val1_id 中,金额将始终存储在该行内的 val1_amount 中,但相同的 val_id 可能会出现在不同行的不同 val?_id 中(但金额会在相应的列中)

4

4 回答 4

6

好吧,在你打了设计这个的人之后,你可以尝试UNPIVOT你的列,然后简单地SUM选择val_amount结果列。我不会真正使用UNPIVOT,但我正在做同样的事情CROSS APPLY

SELECT x.Val_id, SUM(x.val_amount) Val_Amount
FROM dbo.foo t
CROSS APPLY 
(
    VALUES
        (t.val1_id, t.val1_amount),
        (t.val2_id, t.val2_amount),
        (t.val3_id, t.val3_amount),
        (t.val4_id, t.val4_amount)
) x (Val_id, val_amount)
GROUP BY x.Val_id;

这是一个带有现场演示的 sqlfiddle供您尝试。

于 2013-04-22T17:43:35.277 回答
1

我是使用 COALESCE 函数完成的。我不清楚为什么我必须做一个嵌套查询,但我不能让它接受它:

select id, sum(amount)
FROM 
   (SELECT COALESCE(val1_id , val2_id , val3_id , val4_id) id, 
       COALESCE(val1_amount , val2_amount , val3_amount , val4_amount) amount  
    from foo) coalesced_data 
GROUP BY ID

http://sqlfiddle.com/#!3/2ef35/6

于 2013-04-22T17:54:34.227 回答
0

Is there a way to produce output that will group by the val_id from the foo table and SUM the amount values from the foo table, given that the val_id/amount may be stored in any of the val?_id/val?_amount columns?

Hell is other people's data. You might do something like this:

create view FOO as
select foo.id, val1_id as valueid, val1_amount as amt from T
union all
select foo.id  val2_id as valueid, val2_amount as amt from T
union all
select foo.id  val3_id as valueid, val3_amount as amt from T
union all
select foo.id  val4_id as valueid, val4_amount as amt from T
于 2013-04-22T17:53:51.520 回答
0

如果您已正确声明该值只会出现在一对(val_id, val_amount)列中,而其他 3 对为空白,那么这将比当前接受的答案更好(@lamak's)

select id = coalesce(val1_id, val2_id, val3_id, val4_id),
       val = sum(coalesce(val1_amount, val2_amount, val3_amount, val4_amount))
from foo
group by coalesce(val1_id, val2_id, val3_id, val4_id);

这很容易理解,即使重复 COALESCE,它实际上只评估一次,因此没有性能损失。查询计划估计为其他查询成本的 50%。

当前接受的答案也可能会产生一个幻像 NULL 行,例如对于我的 SQL fiddle 演示中不包含第三对 (val3_amount) 中的任何内容的数据。

SQL Fiddle 演示

于 2013-04-23T10:45:06.293 回答