2008-11-25 2 views
0

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

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; 

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

ответ

1

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

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

Спасибо. Я не знаю, почему я об этом не думал. Думаю, я просто ненавижу заявления на выборку в качестве значений столбцов.В любом случае количество потенциальных чтений, генерируемых запросом, велико: это то, что я хочу уменьшить. – Chris 2008-11-25 19:03:21

+0

Я сделаю один без вложенных запросов для вас. – 2008-11-25 19:05:36

1
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 
0

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

INSERT и т.д.

ВЫБОР a.sessionid, d1.activity_description, d2.activity_description

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

РЕГИСТРИРУЙТЕСЬ подробно d1 = О a.sessionid d1.sessionid РЕГИСТРИРУЙТЕСЬ подробно d2 = О a.sessionid d2.sessionid

ГДЕ НЕ СУЩЕСТВУЕТ
(SELECT 1 FROM подробно Где SessionID = a.sessionid и создал < d1.created)

И НЕ СУЩЕСТВУЕТ
(SELECT 1 FROM ДЭТА ил ГДЕ SessionID = a.sessionid и создали> d2.created)

0

Или

ВСТАВИТЬ т.д.

(ВЫБОР Описание ОТ подробно d1 ГДЕ d1.sessionid = a.sessionid
И НЕ СУЩЕСТВУЕТ (SELECT 1 FROM подробно КУДА создано < d1.created)) А.С. DESC1,

(SELECT описание ОТ подробно d2 ГДЕ d2.sessionid = a.sessionid
И НЕ СУЩЕСТВУЕТ (SELECT 1 FROM подробно d2 ГДЕ создано> d1. создано)) AS desc2

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

(я предпочитаю этот один я.)

Смежные вопросы