0

我有一个简单的查询,它返回以下行:

当前行:

Empl    ECode   DCode       LCode       Earn    Dedn    Liab
====    ====    =====       =====       ====    ====    ====
123     PerHr   Null        Null        13      0       0
123     Null    Union       Null        0       10      0
123     Null    Per         Null        0       20      0
123     Null    Null        MyHealth    0       0       5
123     Null    Null        401         0       0       10
123     Null    Null        Train       0       0       15
123     Null    Null        CAFTA       0       0       20

但是,我需要看到上面的行如下:

Empl    ECode   DCode   LCode       Earn    Dedn    Liab
====    ====    =====   =====       ====    ====    ====
123     PerHr   Union   MyHealth    13      10      5
123     Null    Per     401         0       20      10
123     Null    Null    Train       0       0       15
123     Null    Null    CAFTA       0       0       20

这更像是将后续行合并到前面的行中,只要遇到EarnCode, DednCode&的空值LiabCode。实际上我想看到的是将所有内容汇总到前面的行。

在 Oracle 中,我们有这个LAST_VALUE可以使用的函数,但在这种情况下,我根本不知道如何处理它。

在上面的示例中,ECode的总和值列是EarnDCodeisDednLCodeis Liab;请注意,只要ECodeDCode或中的任何一个不为空,就会在、或列LCode中存在相应的值。EarnDednLiab

顺便说一句,我们在工作中使用的是 SQL Server 2008 R2。

希望得到您的建议,谢谢。

4

3 回答 3

1

这与 Tango_Guy 的技术基本相同,但没有临时表并且排序明确。因为每个 Empl 的行数 <= 已经存在的行数,所以我不需要为最左边的表创建一个虚拟表,只需将基础数据过滤到 3 个代码中匹配的位置。此外,我回顾了您的讨论,并将 Earn 和 ECode 一起移动。实际上,没有 ECode 的列中的非零 Earn 会被有效地丢失(这是一个很好的约束情况 - 当 ECode 为 NULL 时,不允许非零 Earn):

http://sqlfiddle.com/#!3/7bd04/3

CREATE TABLE data(ID INT IDENTITY NOT NULL,
                  Empl VARCHAR(3), 
                  ECode VARCHAR(8), 
                  DCode VARCHAR(8), 
                  LCode VARCHAR(8),
                  Earn INT NOT NULL,
                  Dedn INT NOT NULL,
                  Liab INT NOT NULL ) ;

INSERT INTO data (Empl, ECode, DCode, LCode, Earn, Dedn, Liab)
VALUES ('123', 'PerHr', NULL, NULL, 13, 0, 0),
        ('123', NULL, 'Union', NULL, 0, 10, 0),
        ('123', NULL, 'Per', NULL, 0, 20, 0),
        ('123', NULL, NULL, 'MyHealth', 0, 0, 5),
        ('123', NULL, NULL, '401', 0, 0, 10),
        ('123', NULL, NULL, 'Train', 0, 0, 15),
        ('123', NULL, NULL, 'CAFTA', 0, 0, 20);

WITH basedata AS (
    SELECT *, ROW_NUMBER () OVER(ORDER BY ID) AS OrigSort, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY ID) AS EmplSort
    FROM data
),
E AS (
  SELECT Empl, ECode, Earn, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY OrigSort) AS EmplSort
  FROM basedata
  WHERE ECode IS NOT NULL
),
D AS (
  SELECT Empl, DCode, Dedn, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY OrigSort) AS EmplSort
  FROM basedata
  WHERE DCode IS NOT NULL
),
L AS (
  SELECT Empl, LCode, Liab, ROW_NUMBER () OVER(PARTITION BY Empl ORDER BY OrigSort) AS EmplSort
  FROM basedata
  WHERE LCode IS NOT NULL
)
SELECT basedata.Empl, E.ECode, D.Dcode, L.LCode, E.Earn, D.Dedn, L.Liab
FROM basedata
LEFT JOIN E
    ON E.Empl = basedata.Empl AND E.EmplSort = basedata.EmplSort
LEFT JOIN D
    ON D.Empl = basedata.Empl AND D.EmplSort = basedata.EmplSort
LEFT JOIN L
    ON L.Empl = basedata.Empl AND L.EmplSort = basedata.EmplSort
WHERE E.ECode IS NOT NULL OR D.DCode IS NOT NULL OR L.LCode IS NOT NULL
ORDER BY basedata.Empl, basedata.EmplSort
于 2012-08-15T04:44:06.257 回答
0

不确定它是否是您需要的,但您是否尝试过 coalesc

SELECT Name, Class, Color, ProductNumber,
COALESCE(Class, Color, ProductNumber) AS FirstNotNull
FROM Production.Product ;
于 2012-08-15T03:57:49.940 回答
0

我有一个解决方案,但它非常笨拙。如果有人有更好的东西,那就太好了。

但是,一个算法:

1) 获取列中每个不同值列表的行
号 2) 根据行号连接所有列

例子:

select Distinct ECode   into #Ecode     from source_table   order by rowid;
select Distinct DCode   into #Dcode     from source_table   order by rowid;
select Distinct LCode   into #Lcode     from source_table   order by rowid;
select Distinct Earn    into #Earn  from source_table   order by rowid;
select Distinct Dedn    into #Dedn  from source_table   order by rowid;
select Distinct Liab    into #Liab  from source_table   order by rowid;

select b.ECode, c.DCode, d.LCode, e.Earn, f.Dedn, g.Liab
from source_table   a -- Note:  a source for row numbers that will be >= the below
left outer join #Ecode b on a.rowid = b.rowid
left outer join #DCode c on a.rowid = c.rowid
left outer join #LCode d on a.rowid = d.rowid
left outer join #Earn  e on a.rowid = e.rowid
left outer join #Dedn  f on a.rowid = f.rowid
left outer join #Liab  g on a.rowid = g.rowid
where 
    b.ecode is not null or
    c.dcode is not null or
    d.lcode is not null or
    e.earn is not null or
    f.dedn is not null or
    g.liab is not null;

我没有包括 Empl,因为我不知道你想让它扮演什么角色。如果对于给定的 Empl 这一切都是正确的,那么您可以添加它,加入它,然后执行它。

我根本不喜欢这个解决方案,所以希望其他人会想出更优雅的东西。

最好的,大卫

于 2012-08-15T04:11:01.220 回答