Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Из таблицы [History] надо выбрать номера счетов [HI_SHIT] с датой выставления [HI_DATE] и кодом пассажира [HI_DGCOD], соответствующим коду [DG_CODE] в таблице [Dogovor], если первичные договора попадают в диапазон дат [DG_CRDATE], '01.04.2015' и '18.04.2015', и выполняется еще несколько несущественных для моей проблемы условий.

Вопрос в том, что запрос возвращает по каждому клиенту не одну, а несколько записей потому что могло выставляться несколько счетов, и они могут различаться даже на пару секунд по времени выставления. А правильным считается последний счет (по дате/времени выставления).

HI_DGCOD    HI_SHIT    HI_DATE
77151 9551чл 2015-04-16 14:09:32.310
77151 9552чл 2015-04-16 14:09:35.600
Вот фрагмент запроса, который вызывает проблему:
SELECT
  *
FROM
  [db1].[dbo].[Dogovor] AS d,	-- таблица деталей договоров
  [db1].[dbo].[History] AS hs	-- история документов по договорам
WHERE
  d.DG_CRDATE >= '20150401'	-- договор заключен с '20150401'
  AND d.DG_CRDATE <= '20150418' -- договор заключен по '20150418'
  AND EXISTS (
    SELECT			-- подзапрос
        hs.HI_SHIT,		-- выбрать номер счета
	hs.HI_DATE		-- выбрать дату/время записи
    FROM [db1].[dbo].[History]	-- из таблицы истории
    WHERE
        hs.HI_DGCOD = d.DG_CODE	-- номер договора в таблице истории соответствует номеру в таблице договоров
        AND hs.HI_ENABLED = '1'	-- счет не аннулирован
        AND hs.HI_MOD = 'shit'	-- признак того, что это счет на оплату, а не другой документ
  )
  -- ........... - тут еще несколько условий, но они не имеют значения
ORDER BY
  d.DG_CRDATE

Как при помощи такого Sql-запроса для каждого договора получить только одну запись с последним номером счета [HI_SHIT]?
19 апр 15, 23:06    [17536994]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
anvg
Member

Откуда: СПб
Сообщений: 101
Доброе время суток
Если правильно понял
Select hs.HI_DGCOD,HI_hs.HI_SHIT,hs.HI_DGCOD
From db1.dbo.Dogovor dg
	Inner Join db1.dbo.History hs On dg.DG_CODE=hs.HI_DGCOD
Where
	dg.DG_CRDATE >= '20150401' AND dg.DG_CRDATE <= '20150418' 
	And hs.HI_DATE =
	(Select Max(mhs.HI_DATE) From db1.dbo.History mhs
	Where mhs.DGCOD=dg.DG_CODE And
	mhs.HI_ENABLED='1' And mhs.HI_MOD='shit')

Успехов
20 апр 15, 02:06    [17537193]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Добрый Э - Эх
Guest
pinkrose,

Любым из приведенных тут способом
20 апр 15, 06:29    [17537256]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Merdoc
Member

Откуда: Новосибирск
Сообщений: 103
pinkrose,

А время всегда различается, или может быть несколько счетов по одному договору с одинаковым временем?
20 апр 15, 07:09    [17537284]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
anvg
Select hs.HI_DGCOD,HI_hs.HI_SHIT,hs.HI_DGCOD

HI_hs.HI_SHIT - это ошибка, надо hs.HI_SHIT или это какая то хитрость?
anvg
From db1.dbo.Dogovor dg
А тут после From можно перечислить еще кучу таблиц?
Правильно я поняла, что квадратные скобки и "AS" можно не указывать, а одна и та же таблица в разных местах запроса должна быть с разными псевдонимами?
anvg
Inner Join db1.dbo.History hs On dg.DG_CODE=hs.HI_DGCOD
Where
	dg.DG_CRDATE >= '20150401' AND dg.DG_CRDATE <= '20150418' 
	And hs.HI_DATE =
	(Select Max(mhs.HI_DATE) From db1.dbo.History mhs
	Where mhs.DGCOD=dg.DG_CODE And
	mhs.HI_ENABLED='1' And mhs.HI_MOD='shit')
Успехов
Попытаюсь запустить на сервере.

Я привела только проблемную часть запроса, в реальности он намного сложнее и нужные части добавляются программой на VB в зависимости от значений контролов формы и кучи "If ... Then ... Else" по ходу кода.
Вот я и хотела просто добавить подзапрос, если нужно получить номер счета по клиенту. Но уперлась в то, что возвращается не одна запись, а все счета для клиента с интересующим d.DG_CODE

Запрос у меня примерно такой
SELECT
	-- тут перечислены 37 разных полей, которые нужны моей программе
FROM
	-- тут перечислены 8 разных таблиц базы, с псевдонимами, из которой должны браться данные
WHERE
	d.DG_CRDATE >= 'договор заключен с'	   --  подставляется переменная, например, '20150401'
	AND d.DG_CRDATE <= 'договор заключен по' --  подставляется переменная, например, '20150418'

	AND ....
	....     -- тут разные дополнительные условия для получения данных из разных таблиц
	AND ....

	AND EXISTS (	...  -- подзапрос к другой таблице
		SELECT....	-- список полей для подзапроса
		FROM [db1].[dbo].[...]	-- таблица, к которой этот подзапрос
		WHERE ... AND ... AND...	-- список условий для подзапроса
	)

	AND EXISTS (	...  -- другой подзапрос к еще одной таблице
		SELECT ....	-- список полей для подзапроса
		FROM [db1].[dbo].[...]	-- таблица, к которой этот подзапрос
		WHERE ... AND ... AND ...	-- список условий для подзапроса
	)

	AND d.Disabled IS NULL	-- всегда это условие
ORDER BY
	d.DG_CRDATE		-- всегда сортировка по дате договора


Например, если надо добавить курс евро от которого считался договор, то у меня это так:
If Cours = True Then 
	req = req & "AND EXISTS (SELECT v.RC_DATEBEG FROM [db1].[dbo].[CoursesCB] _
		WHERE v.RC_RCOD1 = 'рб' AND v.RC_RCOD2 = 'EU' _
		AND convert(date, d.DG_CRDATE, 112) = convert(date, v.RC_DATEBEG, 112) )"
End If 
20 апр 15, 13:58    [17539450]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Добрый Э - Эх
pinkrose,
Любым из приведенных тут способом

Спасибо, Добрый Э - Эх!!!
Тут столько всего - до вечера буду изучать!
20 апр 15, 14:00    [17539460]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Merdoc
А время всегда различается, или может быть несколько счетов по одному договору с одинаковым временем?

Дата/время документа записывается каждый раз, когда оператор нажимает "Сформировать".
Иногда могут различаться даже доли секунды. Почему это, совсем не понимаю так как каждая команда по сети выполняется несколько секунд.
20 апр 15, 14:02    [17539491]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Вроде что-то получилось, но теперь выдает только тех клиентов, которым был выставлен счет, а не всех для которых выполняется условие

d.DG_CRDATE >= '20150401' AND d.DG_CRDATE <= '20150418' AND d.Disabled IS NULL

Как это можно решить?
21 апр 15, 16:48    [17544998]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Добрый Э - Эх
Guest
pinkrose,

Скорее всего, где-то аутер джойн потерялся... возможно, where "срезало" аутер джойн до иннера. или изначально джойн был "внутренним". показывай текст запроса полностью... иначе можно только гадать и тыкать пальцем в небо.
21 апр 15, 18:04    [17545344]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Добрый Э - Эх
Скорее всего, где-то аутер джойн потерялся... возможно, where "срезало" аутер джойн до иннера. или изначально джойн был "внутренним".

У меня запрос без Inner Join. Иначе не получается работать одновременно с кучей таблиц.

Сейчас я мучаю такой запрос:
SELECT
	d.DG_CODE,
	d.DG_CRDATE,
	d.DG_MAINMEN,
	d.DG_Ticket,
	d.DG_COST,
	d.DG_Discount,
	hs.HI_DATE,
	hs.HI_SHIT,
FROM
	[db1].[dbo].[Dogovor] AS d,
	[db1].[dbo].[History] AS hs
WHERE
	d.Disabled IS NULL
	AND d.DG_CRDATE >= '20150401'
	AND d.DG_CRDATE <= '20150418'
	AND hs.HI_DATE = (
		SELECT
			MAX(mhs.HI_DATE)
		FROM
			[db1].[dbo].[History] AS mhs
		WHERE
			mhs.DGCOD = dg.DG_CODE
			AND mhs.HI_ENABLED = '1'
			AND mhs.HI_MOD = 'shit'
	)
ORDER BY
	d.DG_CRDATE


Не хочет выдавать всех клиентов для заданного диапазона дат, а только тех, кому выставлялся счет.
21 апр 15, 19:34    [17545674]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
ЦБ
Member [заблокирован]

Откуда:
Сообщений: 2773
pinkrose
Добрый Э - Эх
Скорее всего, где-то аутер джойн потерялся... возможно, where "срезало" аутер джойн до иннера. или изначально джойн был "внутренним".

У меня запрос без Inner Join. Иначе не получается работать одновременно с кучей таблиц.

Сейчас я мучаю такой запрос:
SELECT
	d.DG_CODE,
	d.DG_CRDATE,
	d.DG_MAINMEN,
	d.DG_Ticket,
	d.DG_COST,
	d.DG_Discount,
	hs.HI_DATE,
	hs.HI_SHIT,
FROM
	[db1].[dbo].[Dogovor] AS d,
	[db1].[dbo].[History] AS hs
WHERE
	d.Disabled IS NULL
	AND d.DG_CRDATE >= '20150401'
	AND d.DG_CRDATE <= '20150418'
	AND hs.HI_DATE = (
		SELECT
			MAX(mhs.HI_DATE)
		FROM
			[db1].[dbo].[History] AS mhs
		WHERE
			mhs.DGCOD = dg.DG_CODE
			AND mhs.HI_ENABLED = '1'
			AND mhs.HI_MOD = 'shit'
	)
ORDER BY
	d.DG_CRDATE


Не хочет выдавать всех клиентов для заданного диапазона дат, а только тех, кому выставлялся счет.
Этот запрос просто какую-то "херь", в виде кросс джойна двух, никак не связанных выборок, должен "выдавать"!
Где связь между таблицами??
21 апр 15, 19:52    [17545736]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Добрый Э - Эх
Guest
pinkrose
У меня запрос без Inner Join. Иначе не получается работать одновременно с кучей таблиц.

Так-то джойны как раз для того и придумывались, чтобы работать с кучей связанных друг с другом таблиц.
22 апр 15, 05:05    [17546655]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1873
SELECT TOP 1 WITH TIES
	d.DG_CODE,
	d.DG_CRDATE,
	d.DG_MAINMEN,
	d.DG_Ticket,
	d.DG_COST,
	d.DG_Discount,
	hs.HI_DATE,
	hs.HI_SHIT
FROM [db1].[dbo].[Dogovor] AS d	-- таблица деталей договоров
LEFT JOIN [db1].[dbo].[History] AS hs	-- история документов по договорам
ON hs.HI_DGCOD = d.DG_CODE	 -- номер договора в таблице истории соответствует номеру в таблице договоров
 AND hs.HI_ENABLED = '1'	-- счет не аннулирован
 AND hs.HI_MOD = 'shit'	-- признак того, что это счет на оплату, а не другой документ
WHERE d.DG_CRDATE >= '20150401'	-- договор заключен с '20150401'
  AND d.DG_CRDATE <= '20150418' -- договор заключен по '20150418'
ORDER BY ROW_NUMBER()OVER(PARTITION BY d.DG_CODE ORDER BY ISNULL(hs.HI_DATE,'19000101') DESC)
22 апр 15, 07:02    [17546695]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
LexusR
SELECT TOP 1 WITH TIES
	d.DG_CODE,
	d.DG_CRDATE,
	d.DG_MAINMEN,
	d.DG_Ticket,
	d.DG_COST,
	d.DG_Discount,
	hs.HI_DATE,
	hs.HI_SHIT
FROM [db1].[dbo].[Dogovor] AS d	-- таблица деталей договоров
LEFT JOIN [db1].[dbo].[History] AS hs	-- история документов по договорам
ON hs.HI_DGCOD = d.DG_CODE	 -- номер договора в таблице истории соответствует номеру в таблице договоров
 AND hs.HI_ENABLED = '1'	-- счет не аннулирован
 AND hs.HI_MOD = 'shit'	-- признак того, что это счет на оплату, а не другой документ
WHERE d.DG_CRDATE >= '20150401'	-- договор заключен с '20150401'
  AND d.DG_CRDATE <= '20150418' -- договор заключен по '20150418'
ORDER BY ROW_NUMBER()OVER(PARTITION BY d.DG_CODE ORDER BY ISNULL(hs.HI_DATE,'19000101') DESC)
 AND d.DG_CRDATE < '20150419' -- договор заключен по '20150418'
22 апр 15, 09:22    [17547022]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
LexusR,

и почему
ORDER BY ISNULL(hs.HI_DATE,'19000101') DESC
а не
ORDER BY hs.HI_DATE DESC
?
22 апр 15, 09:25    [17547029]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Добрый Э - Эх
pinkrose
У меня запрос без Inner Join. Иначе не получается работать одновременно с кучей таблиц.

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

Вы можете привести пример как при помощи Join сделать запрос не из двух, а из восьми таблиц?

У меня в универе были лекции по реляционным базам данных, этими конспектами пользуюсь, как руководством к практическим действиям.
В моем конспекте есть такой пример для выборки из двух связанных таблиц:
SET value1 = 100
SELECT
	t1.field_1_1,
	t1.field_1_2,
	t2.field_2_1,
	t2.field_2_2
FROM
	[table1] AS t1,
	[table2] AS t2
WHERE
	t1.field_1_1 = value1	-- основное условие
	AND
	t2.field_2_1 = t1.field_1_2	-- связанное условие
ORDER BY
	t1.field_1_1

запрос выдает:
field_1_1	field_1_2	field_2_1	field_2_2
100 200 200 Иван

Никакой Join не упоминается вообще. Зато таким образом я получаю данные из восьми таблиц, просто их перечисляю в секции запроса FROM.
Что я делаю не так?
22 апр 15, 11:19    [17547605]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Glory
Member

Откуда:
Сообщений: 104760
pinkrose
Вы можете привести пример как при помощи Join сделать запрос не из двух, а из восьми таблиц?

Написать 7 раз JOIN

pinkrose
Что я делаю не так?

Используете устаревший синтаксис
22 апр 15, 11:22    [17547626]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
iap
AND d.DG_CRDATE < '20150419' -- договор заключен по '20150418'

по - имеется в виду, что включая эту дату, поэтому - <=
22 апр 15, 11:24    [17547638]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Добрый Э - Эх
Guest
pinkrose
У меня в универе были лекции по реляционным базам данны
судя по всему, лекции ты, всё же, прогуляла. ведь в конспекте написано - связанное условие. где оно в твоем запросе?

pinkrose
Никакой Join не упоминается вообще.
эти претензии направь своему преподу. пусть перепишет методички. ибо в 2015 года и при наличии 2014 сервера грустно использоватьстарообрядные запятушечно-веерные джойны.

pinkrose
Что я делаю не так?
как минимум не читаешь актуальную документацию по используемой СУБД, не понимаешь сути того, чего законспектировала, не применяешь полученные теоретические знания на практике. а если и применяешь, то неправильно.. приведенный тобой же пример кода - яркое тому подтверждение.
22 апр 15, 11:32    [17547674]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
pinkrose
Member

Откуда:
Сообщений: 56
Glory
pinkrose
Вы можете привести пример как при помощи Join сделать запрос не из двух, а из восьми таблиц?

Написать 7 раз JOIN

Можете привести пример?
pinkrose
Что я делаю не так?

Glory
Используете устаревший синтаксис

Простите великодушно, но меня так учили, про Join не говорилось. Базы данных - это одна из немногих тем, которые я не прогуляла :)
Даже попался билет с задачей, где надо было что-то с SQL-запросами делать, я даже тогда "отлично" получила :)
22 апр 15, 11:33    [17547677]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Glory
Member

Откуда:
Сообщений: 104760
pinkrose
Можете привести пример?

JOIN ...ON ...
JOIN ...ON ...
JOIN ...ON ...
JOIN ...ON ...
JOIN ...ON ...
JOIN ...ON ...
JOIN ...ON ...

pinkrose
Простите великодушно, но меня так учили, про Join не говорилось

Мне то все равно. А вот быть может уже в следующей версии сервер вас не простит и пошлет подальше
22 апр 15, 11:36    [17547686]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Добрый Э - Эх
Guest
Glory,

если рвать шаблоны, то сразу по полной:
join ...
  join ...
    join ...
      join ...
        join ...
          join ...
            join ...
            on ...
          on ...
        on ...
      on ...
    on ...
  on ...
on ...
а то потом предъявит нам, что мы её не рассказали про вложенные джойны.
22 апр 15, 11:39    [17547700]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
buser
Member

Откуда: Санкт-Петербург
Сообщений: 4537
pinkrose
Простите великодушно, но меня так учили, про Join не говорилось. Базы данных - это одна из немногих тем, которые я не прогуляла :)
Даже попался билет с задачей, где надо было что-то с SQL-запросами делать, я даже тогда "отлично" получила :)


Да, это не просто "устаревший" синтаксис... это еще и "скрытые в траве грабли".... а по поводу отлично... учился я с одной девочкой на потоке, что двух строк кода написать не могла... с удивлением узнал, что уехала заморским олухам "базы данных" преподавать
22 апр 15, 11:40    [17547702]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Добрый Э - Эх
Guest
Glory
Мне то все равно. А вот быть может уже в следующей версии сервер вас не простит и пошлет подальше
кстати, а старообрядные внешние джойны через where + , + =* ещё работают или уже запрещены?

З.Ы.
сервера под рукой для проверки нет.
22 апр 15, 11:42    [17547709]     Ответить | Цитировать Сообщить модератору
 Re: Как найти самую позднюю дату-время при помощи подзапроса?  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
Добрый Э - Эх, а они были когда то разрешены? Вроде бы только Oracle такой синтаксис поддерживал.
22 апр 15, 11:42    [17547712]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить