5

私の同僚は、SQL クエリに問題があります:-

例として、次の 2 つの一時テーブルを取り上げます。

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

「Dave」は #jobs テーブルに存在しないため、予想どおり NULL 値が与えられます。

私の同僚は、各 NULL 値が前のエントリと同じ値になるようにクエリを変更したいと考えています。

したがって、上記は次のようになります。

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

Dave が「ドライバー」になったことに注意してください

複数の 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」が最後の非 null エントリであるためです。

4

2 に答える 2

6

おそらくこれを行うためのより良い方法があります。これは、 Common Table Expressions (CTE)を使用して結果を達成し、その出力を使用してOUTER APPLYを実行し、前の人の仕事を見つける方法の 1 つです。ここで使用idするクエリは、レコードを並べ替えてから、前の人の仕事が何であったかを判断します。テーブル内のデータは順序付けられていないセットと見なされるため、レコードを並べ替えるには少なくとも 1 つの条件が必要です。

また、シーケンスの最初の人が仕事を持っている必要があるという前提があります。最初の人が仕事を持っていなければ、選ぶ価値はありません。

SQL Fiddle でデモを表示するには、ここをクリックしてください。

ここをクリックして、2 番目のデータ セットを使用した 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

「最後の」非 null エントリとはどういう意味ですか? 「最後」に一貫した意味を持たせるには、明確に定義された順序が必要です。「値」列を使用して最後に定義するデータ定義を含むクエリを次に示します。これは、必要なものに近い可能性があります。

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 に答える