5

我的一个同事有一个 sql 查询的问题:-

以以下为例,两个临时表:-

select 'John' as name,10 as value into #names
UNION ALL SELECT 'Abid',20 
UNION ALL SELECT 'Alyn',30 
UNION ALL SELECT 'Dave',15;

select 'John' as name,'SQL Expert' as job into #jobs
UNION ALL SELECT 'Alyn','Driver' 
UNION ALL SELECT 'Abid','Case Statement';

我们在表上运行以下查询来给我们一个连接的结果集:-

select #names.name, #names.value, #jobs.job
FROM #names left outer join #jobs
on #names.name = #jobs.name

name    value    job
John    10       SQL Expert
Abid    20       Case Statement
Alyn    30       Driver
Dave    15       NULL

由于#jobs 表中不存在“Dave”,因此按预期为他提供了一个NULL 值。

我的同事想要修改查询,以便为每个 NULL 值赋予与前一个条目相同的值。

所以上面将是: -

name    value    job
John    10       SQL Expert
Abid    20       Case Statement
Alyn    30       Driver
Dave    15       Driver

请注意,戴夫现在是“司机”

序列中可能有多个 NULL 值,

name    value    job
John    10       SQL Expert
Abid    20       Case Statement
Alyn    30       Driver
Dave    15       NULL
Joe     15       NULL
Pete    15       NULL

在这种情况下,Dave、Joe 和 Pete 都应该是“Driver”,因为“Driver”是最后一个非空条目。

4

2 回答 2

6

可能有更好的方法来做到这一点。这是我可以使用公用表表达式 (CTE)实现结果并使用该输出执行OUTER APPLY以查找上一个 persion 的工作的方法之一。这里的查询用于id对记录进行排序,然后确定前一个人的工作是什么。您至少需要一个标准来对记录进行排序,因为表中的数据被视为无序集。

此外,假设序列中的第一个人应该有工作。如果第一个人没有工作,那么选择就没有价值。

单击此处查看 SQL Fiddle 中的演示。

单击此处查看 SQL Fiddle 中的另一个演示,其中包含第二个数据集。

脚本

 CREATE TABLE names
    (
            id      INT         NOT NULL IDENTITY
      ,     name    VARCHAR(20) NOT NULL
      ,     value   INT         NOT NULL
    );

    CREATE TABLE jobs
    (
            id  INT         NOT NULL
      ,     job VARCHAR(20) NOT NULL
    );

    INSERT INTO names (name, value) VALUES
      ('John', 10),
      ('Abid', 20),
      ('Alyn', 30),
      ('Dave', 40),
      ('Jill', 50),
      ('Jane', 60),
      ('Steve', 70);

    INSERT INTO jobs (id, job) VALUES
      (1, 'SQL Expert'),
      (2, 'Driver' ),
      (5, 'Engineer'),
      (6, 'Barrista');

    ;WITH empjobs AS
    (
        SELECT
        TOP 100 PERCENT n.id
                    ,   n.name
                    ,   n.value
                    ,   job
        FROM            names n 
        LEFT OUTER JOIN jobs j
        on              j.id = n.id
        ORDER BY        n.id
    ) 
    SELECT      e1.id
            ,   e1.name
            ,   e1.value
            ,   COALESCE(e1.job , e2.job) job FROM empjobs e1
    OUTER APPLY (
                  SELECT 
                  TOP 1     job 
                  FROM      empjobs     e2
                  WHERE     e2.id   < e1.id
                  AND       e2.job  IS NOT NULL
                  ORDER BY  e2.id   DESC
                ) e2;

输出

ID  NAME    VALUE  JOB
--- ------  -----  -------------
1   John      10   SQL Expert
2   Abid      20   Driver
3   Alyn      30   Driver
4   Dave      40   Driver
5   Jill      50   Engineer
6   Jane      60   Barrista
7   Steve     70   Barrista
于 2012-05-01T10:17:06.857 回答
0

“最后一个”非空条目是什么意思?您需要明确定义的“last”顺序才能具有一致的含义。这是一个带有数据定义的查询,它使用“值”列来定义最后一个,这可能与您想要的很接近。

CREATE TABLE #names
    (
            id      INT         NOT NULL IDENTITY
      ,     name    VARCHAR(20) NOT NULL
      ,     value   INT         NOT NULL PRIMARY KEY
    );

    CREATE TABLE #jobs
    (
            name  VARCHAR(20)         NOT NULL
      ,     job VARCHAR(20) NOT NULL
    );

    INSERT INTO #names (name, value) VALUES
      ('John', 10),
      ('Abid', 20),
      ('Alyn', 30),
      ('Dave', 40),
      ('Jill', 50),
      ('Jane', 60),
      ('Steve', 70);

    INSERT INTO #jobs (name, job) VALUES
      ('John', 'SQL Expert'),
      ('Abid', 'Driver' ),
      ('Alyn', 'Engineer'),
      ('Dave', 'Barrista');

with Partial as (
  select
  #names.name,
  #names.value,
  #jobs.job as job
  FROM #names left outer join #jobs
  on #names.name = #jobs.name
)
  select
    name,
    value,
    (
      select top 1 job
      from Partial as P
      where job is not null
      and P.value <= Partial.value
      order by value desc
    )
  from Partial;

插入数据然后更新可能更有效。

于 2012-05-01T12:48:04.553 回答