2009-07-03 1 views
0

У меня есть таблица MSSQL Server, как это:SQL SERVER: View, чтобы получить максимальное и минимальное значение из таблицы

id (auto-increment) 
amount 
date 
account_id 

Данные вставляются в течение дня. Теперь мне нужно посмотреть, как открыть и закрыть суммы для каждой учетной записи за каждый день. Моя проблема заключается в создании быстрого запроса для доступа к минимальным и максимальным значениям. Создание представления для доступа только к минимуму отлично с помощью инструкции in, однако получение минимума и максимума является сложным. Я пробовал использовать предложение with, но запрос невероятно медленный.

BTW Я сопоставляю представление с гибернацией, поэтому хранимые процедуры и функции не будут работать одинаково (что я знаю).

Обновление Я думаю, что мой вопрос не был ясен из ответов, которые я получил. Я хочу получить баланс открытия и закрытия для каждой учетной записи. Максимум и минимум относятся к получению max и min (id) при группировке по дате и account_id. Я хочу получить сумму, когда идентификатор равен максимальному id (баланс закрытия) и сумма, когда идентификатор равен минимальному id (начальный баланс) для каждой учетной записи за каждый день.

+0

Я не собираюсь пытаться ответить на это, так как мне не нравится гимнастика SQL и верю, что ваша схема должна быть изменена. Но то, что вы ищете, это строки с минимальным и максимальным id для каждой заданной даты. Это должно дать вам цены открытия и закрытия, если сумма является ценой. Если сумма является изменением цены, вам нужно больше информации, так как у вас нет способа получить цену открытия. И тогда вам придется обрабатывать каждую транзакцию за день, чтобы получить цену закрытия. Это не то, что SQL-запросы, для чего хранятся хранимые процедуры. – paxdiablo

ответ

0

По сути мне нужно следующий запрос, но с утверждением заставляет его работать медленно:

with x as (
select 
    MAX(ab.id) as maxId, MIN(ab.id) as minId 
from Balance ab 
group by ab.account_id, dbo.Get_PeriodDateFromDatetime(ab.StatementDate) 
) 
select 
    ab.Amount as openingBalance, ab2.Amount as closingBalance 
from Balance ab, Balance ab2, x 
where ab.id = x.maxId and ab2.id = x.minId 
+0

Я, должно быть, ошибся в первый раз, когда я это сделал, потому что он работает нормально. – RaelG

1
SELECT account_id, date, MIN(amount), MAX(amount) 
FROM <table> 
GROUP BY account_id, date 

Должно быть что-то не хватает в вашем вопросе.

+0

Предполагается, что он не использует поле datetime с указанием даты и времени :) –

+0

Правда. Однако я обычно ожидаю, что названия будут названы так, как они есть. –

+1

@ Джон Сондерс, Раэль говорит, что он хочет открытия и закрытия. Как будет работать max и min здесь? Например, если пользователь набирает деньги так, что значение идет ниже начальной суммы, тогда ваш запрос будет показывать это как сумму открытия !! Или я ничего не получаю ...? –

0

на основе Джон Сондерс ответ и Джереми комментарий:

SELECT account_id, date, MIN(amount), MAX(amount) 
FROM <table> 
GROUP BY account_id, DatePart(Year, date),DatePart(Month, date), DatePart(Day, date) 
0

Я не знаю, если это улучшает любой, но в запросе, который вы указали, не хватает некоторых частей, таких как account_id, в запросе «с» и присоединяется к account_id в основной части:

with x as (
select 
    ab.account_id, MAX(ab.id) as closeId, MIN(ab.id) as openId 
from Balance ab 
group by ab.account_id, dbo.Get_PeriodDateFromDatetime(ab.StatementDate) 
) 
select 
    opbal.account_id, opbal.StatementDate, 
    opbal.Amount as openingBalance, clsbal.Amount as closingBalance 
from Balance opbal, Balance clbal, x 
where clsbal.id = x.closeId 
and clsbal.ccount_id = x.account_id 
and opbal.id = x.openId 
and op.account_id = x.account_id 

Меня немного беспокоит вызов dbo.Get_PeriodDateFromDatetime (ab.StatementDate): если у вас есть указатель на account_id и StatementDate (у вас есть этот индекс, не так ли? Он также выглядит хорошим кандидатом для кластеризованного индекса), тогда это может быть не так уж плохо, если таблица не массивная.

Как медленно, «медленно», между прочим?

1

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

create table #accounts 
    (
    id   integer identity, 
    account_id integer, 
    amount  decimal(18,3), 
    tran_date datetime 
    ) 
go 

insert into #accounts values (1,124.56,'06/01/2009 09:34:56'); 
insert into #accounts values (1,125.56,'06/01/2009 10:34:56'); 
insert into #accounts values (1,126.56,'06/01/2009 11:34:56'); 

insert into #accounts values (2,124.56,'06/01/2009 09:34:56'); 
insert into #accounts values (2,125.56,'06/01/2009 10:34:56'); 
insert into #accounts values (2,126.56,'06/01/2009 11:34:56'); 

insert into #accounts values (3,124.56,'06/01/2009 09:34:56'); 
insert into #accounts values (3,125.56,'06/01/2009 10:34:56'); 
insert into #accounts values (3,126.56,'06/01/2009 11:34:56'); 

insert into #accounts values (4,124.56,'06/01/2009 09:34:56'); 
insert into #accounts values (4,125.56,'06/01/2009 10:34:56'); 
insert into #accounts values (4,126.56,'06/01/2009 11:34:56'); 

insert into #accounts values (1,124.56,'06/02/2009 09:34:56'); 
insert into #accounts values (1,125.56,'06/02/2009 10:34:56'); 
insert into #accounts values (1,126.56,'06/02/2009 11:34:56'); 

insert into #accounts values (2,124.56,'06/02/2009 09:34:56'); 
insert into #accounts values (2,125.56,'06/02/2009 10:34:56'); 
insert into #accounts values (2,126.56,'06/02/2009 11:34:56'); 

insert into #accounts values (3,124.56,'06/02/2009 09:34:56'); 
insert into #accounts values (3,125.56,'06/02/2009 10:34:56'); 
insert into #accounts values (3,126.56,'06/02/2009 11:34:56'); 

insert into #accounts values (4,124.56,'06/02/2009 09:34:56'); 
insert into #accounts values (4,125.56,'06/02/2009 10:34:56'); 
insert into #accounts values (4,126.56,'06/02/2009 11:34:56'); 
go 

select 
    ranges.tran_day  transaction_day, 
    ranges.account_id account_id, 
    bod.amount   bod_bal, 
    eod.amount   eod_bal 
from 
    -- Subquery to define min/max records per account per day 
    (
    select 
     account_id, 
     cast(convert(varchar(10),tran_date,101) as datetime) tran_day, 
     max(id) max_id, 
     min(id) min_id 
    from 
     #accounts 
    group by 
     account_id, 
     cast(convert(varchar(10),tran_date,101) as datetime) 
    ) ranges 

    -- Beginning of day balance 
    JOIN #accounts bod 
     on (bod.id = ranges.min_id) 

    -- End of day balance 
    JOIN #accounts eod 
     on (eod.id = ranges.max_id) 
go 

Если вам нужна более высокую производительность, сохранить вложенный запрос к временной таблице первого и поставить индекс на нем для соединения. .. это может ускорить его.