C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Запрос, Желательно на MSSQLSERVER2000
Gedeon
Отправлено: 27.05.2004, 16:16


Ветеран

Группа: Модератор
Сообщений: 1742



Че-то уже второй день туплю
одна таблица
id — PK — int, FIO — VARCHAR
вторая
id — int, FWPKey — FK — int, BeginDate — SMALDATETIME, EndDate — SMALLDATETIME
Таблицы связаны по T1.id=T2.FWPKey по соотношению 1 ко многим, как мне получить результат
Id, сумма всех разниц дат (BeginDate — EndDate) в днях например
AVC
Отправлено: 27.05.2004, 17:24


Ветеран

Группа: Модератор
Сообщений: 1583



Что типа этого

Select T1.id, Sum(tmpt.dltd)
From T1,
(Select T2.FWPKey, (T2.EndDate — T2.BeginDate) dltd
From T2
Group By FWPKey
) tmpt
Where T1.id = tmpt.FWPKey
olegenty
Отправлено: 28.05.2004, 07:09


Ветеран

Группа: Модератор
Сообщений: 2412



а по-мему так:
CODE

SELECT DISTINCT
   ID, BEGINDATE, ENDDATE, SUM(ENDDATE — BEGINDATE)
FROM
   TABLE_2
GROUP BY ID, BEGINDATE, ENDDATE
full_lamer
Отправлено: 28.05.2004, 07:38


Машинист паровоза

Группа: Участник
Сообщений: 225



А помоему даты вычитать нельзя...

Помоему так:
select sum (cast (tend as int) — cast (beg as int)) from demo

ЗЫ. Обычно от большей отнимают меньшее (end — begin)...
Nick
Отправлено: 28.05.2004, 08:16


Машинист паровоза

Группа: Участник
Сообщений: 247



А так разве не получается

select FWPKey, Sum (EndDate — BeginDate ) from T2
group by FWPKey

Если допускается Null в датах тогда сложнее
AVC
Отправлено: 28.05.2004, 08:23


Ветеран

Группа: Модератор
Сообщений: 1583



Опс! Так работает (если это то, что требовалось)

Select T1.id, T1.fio, tmp.dltd
From
T1
,(Select T2.fwpkey, Sum(T2.enddate — T2.begdate) dltd
From T2 Group by T2.fwpkey
) tmp
Where T1.id *= tmp.id1

есть сомнение куда поставить звездочку в синтаксисе MSSql
Результат — список всех из T1 + сумма разниц дат для кождого, если есть в T2
olegenty
Отправлено: 28.05.2004, 08:25


Ветеран

Группа: Модератор
Сообщений: 2412



если я правильно понял вопрос, то подразумевались не все разницы, а разницы всех пар.
AVC
Отправлено: 28.05.2004, 08:30


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE
Если допускается Null в датах тогда сложнее

Скорее всего не очень
Если операции с пустыми запрещены (неполная информация -> вычитать нельзя) то ставим фильтр Where begdate is not null and enddate is not null

или заменяем пустые даты на даты по умолчанию. Наверное MSSql имеет функцию, подобную IsNull(prm1, prm2...), которая находит первый не null'ов аргумент.
Gedeon
Отправлено: 28.05.2004, 08:54


Ветеран

Группа: Модератор
Сообщений: 1742



ISNULL есть функция такая, NULL м.б. для каждого id только 1, его меняю на GETDATE(). Запрос сейчас попробую, но идею кажется понял, спасибо, сейчас испытаю напишу, что получилось, там просто все немного сложнее мне надо кол-во полных лет, месяцев, дней для суммы этих дат, но ту функцию я написал, осталось это.
QUOTE

если я правильно понял вопрос, то подразумевались не все разницы, а разницы всех пар.

Да правильно сумма разниц всех пар.
ЗЫ Вычитать из одной даты другую не совсем корректно получается есть такая функция DATEDIFF

Отредактировано Gedeon — 28/05/2004, 10:06
olegenty
Отправлено: 28.05.2004, 09:10


Ветеран

Группа: Модератор
Сообщений: 2412



я ещё не весь набор функций MS SQL знаю smile.gif
Gedeon
Отправлено: 28.05.2004, 09:35


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (olegenty @ 28/05/2004, 10:12)
я ещё не весь набор функций MS SQL знаю smile.gif

Я тоже biggrin.gif
AVC
Отправлено: 28.05.2004, 09:42


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (Gedeon @ 28/05/2004, 08:56)
ЗЫ Вычитать из одной даты другую не совсем корректно

Где как. Но собрались люди грамотные ?
Gedeon
Отправлено: 28.05.2004, 09:55


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (AVC @ 28/05/2004, 10:44)
QUOTE (Gedeon @ 28/05/2004, 08:56)
ЗЫ Вычитать из одной даты другую не совсем корректно

Где как. Но собрались люди грамотные ?

Простите, не пойму Вашего вопроса, помощь Вы мне большую оказали, спасибо всем, сейчас дооформлю все, приведу, что получилось, просто MSSQL ругается на одна дата- вторая в некоторых случаях, если это часть более сложных выражений, а все функции знать по моему просто не реально их там блин немеряно.
AVC
Отправлено: 28.05.2004, 10:01


Ветеран

Группа: Модератор
Сообщений: 1583



Вопрос был риторический, утверждающий что воплотить идею каждый в состоянии.

Отредактировано AVC — 28/05/2004, 10:04
Gedeon
Отправлено: 28.05.2004, 10:47


Ветеран

Группа: Модератор
Сообщений: 1742



Вот результирующий запрос
SQL
Select WP.id,

Sum(DATEDIFF(dd,WJ.endWork,WJ.beginWork))
From WorkJobTitles WJ,
WorkPeoples WP
WHERE WJ.WPKey=WP.Id
GROUP BY WP.id

собственно ничего сложного, просто мне это все еще надо в кучу функций передать, поэтому и руки как-то опускались. Бонусом цепляю запрос, который из таблицы WorkPeoples выбирает id и полное количество лет, месяцев и дней прошедшее с даты expirience в этой таблице до сегодня, может пригодиться кому.
SQL
SELECT Id, 'Лет: ' + CAST(
DATEPART(yyyy,GETDATE())-DATEPART(yyyy,expirience)-
CASE
WHEN (DATEPART(mm,GETDATE())<DATEPART(mm,expirience) or (DATEPART(yyyy,GETDATE())=DATEPART(mm,expirience) and DATEPART(dd,GETDATE())<DATEPART(dd,expirience)))
THEN 1
ELSE 0
END AS VARCHAR(3))
+ ', месяцев: ' + CAST(
DATEDIFF(mm,expirience,GETDATE())-
12*(DATEPART(yyyy,GETDATE())-DATEPART(yyyy,expirience)-
CASE
WHEN (DATEPART(mm,GETDATE())<DATEPART(mm,expirience) or (DATEPART(yyyy,GETDATE())=DATEPART(mm,expirience) and DATEPART(dd,GETDATE())<DATEPART(dd,expirience)))
THEN 1
ELSE 0
END) -
CASE
WHEN DATEPART(dd,GETDATE())<DATEPART(dd,expirience)
THEN 1
ELSE 0
END AS VARCHAR(2))
+ ', дней: ' + CAST(
DATEDIFF(dd,DATEADD(month,(DATEDIFF(mm,expirience,GETDATE())-
12*(DATEPART(yyyy,GETDATE())-DATEPART(yyyy,expirience)-
CASE
WHEN (DATEPART(mm,GETDATE())<DATEPART(mm,expirience) or (DATEPART(yyyy,GETDATE())=DATEPART(mm,expirience) and DATEPART(dd,GETDATE())<DATEPART(dd,expirience)))
THEN 1
ELSE 0
END) -
CASE
WHEN DATEPART(dd,GETDATE())<DATEPART(dd,expirience)
THEN 1
ELSE 0
END), DATEADD(year,(DATEPART(yyyy,GETDATE())-DATEPART(yyyy,expirience)-
CASE
WHEN (DATEPART(mm,GETDATE())<DATEPART(mm,expirience) or (DATEPART(yyyy,GETDATE())=DATEPART(mm,expirience) and DATEPART(dd,GETDATE())<DATEPART(dd,expirience)))
THEN 1
ELSE 0
END),expirience)),GETDATE()) AS NVARCHAR(2)) AS Exp
FROM WorkPeoples

Длинновасто правда и читать тяжело, но работает, я его в UDF засунул поэтому жизнь упрощает.
AVC
Отправлено: 28.05.2004, 12:09


Ветеран

Группа: Модератор
Сообщений: 1583



Не сочтите за умничание — может пригодятся идеи. На Oracle последний запрос выглядит так:
SQL
Select
t1.*
,('Лет ' || Floor(Months_between(sysdate, birthday) / 12) ||
', месяцев ' || Floor(Months_between(sysdate, birthday) - Floor(Months_between(sysdate, birthday) / 12)*12) ||
', дней ' || To_Char
(case when To_Number(To_Char(sysdate,'dd')) >= To_Number(To_Char(birthday,'dd'))
then Floor(To_Date(To_Char(sysdate,'dd.') || To_Char(birthday,'mm.yyyy'), 'dd.mm.yyyy') - birthday)
else Floor(sysdate - Add_Months(birthday, Floor(Months_between(sysdate, birthday))))
end)
) age_info
From Tabel.People t1
Where 1 = 1 and birthday is not Null


Отредактировано AVC — 28/05/2004, 14:10

Вернуться в Работа с базами данных в C++Builder