SQL Server - обновить одну таблицу с первой и последней строками из другой таблицы - PullRequest
0 голосов
/ 25 ноября 2008

У меня есть несколько таблиц, которые используются для регистрации активности пользователя для приложения. Таблицы выглядят примерно так (псевдокод из памяти, может быть синтаксически неправильным):

create table activity (
  sessionid uniqueidentifier not null,
  created smalldatetime not null default getutcdate()
);

create table activity_details (
  sessionid uniqueidentifier not null,
  activity_description varchar(100) not null,
  created smalldatetime not null default getutcdate()
);

Моя цель - заполнить сводную таблицу для целей отчетности, которая выглядит примерно так:

create table activity_summary (
  sessionid uniqueidentifier not null,
  first_activity_desc varchar(100) not null,
  last_activity_desc varchar(100) not null
);

Первое и последнее описания деятельности будут определены в хронологическом порядке. Моя первоначальная мысль состоит в том, чтобы обновить сводную таблицу следующим образом:

truncate table activity_summary;

insert into activity_summary (sessionid)
select sessionid from activity;

update table activity_summary set
  first_activity_desc = (select top 1 activity_desc from activity_detail where sessionid = as.sessionid order by created asc),
  last_activity_summary = (select top 1 activity_desc from activity_detail where sessionid = as.sessionid order by created desc)
from activity_summary as;

Однако это кажется невероятно многословным и ненужным для меня. Я просто не уверен, как уменьшить это. У меня такое чувство, что я могу как-то все это сделать в операторе вставки, но я в тупике. Какие-либо предложения?

Ответы [ 4 ]

1 голос
/ 25 ноября 2008
insert into activity_summary
    (sessionid, first_activity_desc, last_activity_desc)
select
    agg.sessionid,
    adf.activity_description,
    adl.activity_description
from
    (SELECT
         sessionid, MIN(created) as firstcreated, MAX(created) as lastcreated
    from
         activity_detail group by sessionid
    ) agg
    JOIN
    activity_details adf ON agg.sessionid = adf.sessionid AND agg.firstcreated = adf.created
    JOIN
    activity_details adl ON agg.sessionid = adl.sessionid AND agg.lastcreated = adl.created
1 голос
/ 25 ноября 2008

Возможно, есть и более эффективные способы сделать это, но это наиболее близко к вашему оригиналу:

truncate table activity_summary;

insert into activity_summary (sessionid, first_activity_desc, last_activity_summary)
select a.sessionid
,(select top 1 ad.activity_desc from activity_detail AS ad where ad.sessionid = a.sessionid order by ad.created asc) AS first_activity_desc
,(select top 1 ad.activity_desc from activity_detail AS ad where ad.sessionid = a.sessionid order by ad.created desc) AS last_activity_summary
from activity AS a;

Что-то вроде этого может быть более эффективным:

truncate table activity_summary;

WITH firsts AS (
    SELECT ad.sessionid
        ,ad.activity_desc
        ,ROW_NUMBER() OVER (ORDER BY ad.created ASC) as RowNumber
    FROM activity_detail AS ad
)
,lasts AS (
    SELECT ad.sessionid
        ,ad.activity_desc
        ,ROW_NUMBER() OVER (ORDER BY ad.created DESC) as RowNumber
    FROM activity_detail AS ad
)
insert into activity_summary (sessionid, first_activity_desc, last_activity_summary)
select a.sessionid
    ,firsts.activity_desc
    ,lasts.activity_desc
from activity AS a
INNER JOIN firsts ON firsts.sessionid = a.sessionid AND firsts.RowNumber = 1
INNER JOIN lasts ON lasts.sessionid = a.sessionid AND lasts.RowNumber = 1
0 голосов
/ 25 ноября 2008

Или,

Вставка и т. Д.

(ВЫБЕРИТЕ ОПИСАНИЕ ИЗ ДЕТАЛИ d1 ГДЕ d1.sessionid = a.sessionid
И НЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ ДЕТАЛИ, ГДЕ СОЗДАНО

(ВЫБРАТЬ описание ИЗ ДЕТАЛИ d2 ГДЕ d2.sessionid = a.sessionid
И НЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ ДЕТАЛИ d2, ГДЕ СОЗДАНО> d1.created)) AS desc2

ОТ деятельности а

(Я сам предпочитаю это.)

0 голосов
/ 25 ноября 2008

Грубо говоря,

Вставка и т. Д.

SELECT a.sessionid, d1.activity_description, d2.activity_description

FROM activity a

JOIN detail d1 ON a.sessionid = d1.sessionid
JOIN detail d2 ON a.sessionid = d2.sessionid

WHERE NOT EXISTS  
  (SELECT 1 FROM detail WHERE sessionid = a.sessionid AND created < d1.created)

AND NOT EXISTS  
  (SELECT 1 FROM detail WHERE sessionid = a.sessionid AND created > d2.created)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...