Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите с запросом  [new]
aleha
Member

Откуда:
Сообщений: 104
Помогите составить запрос, а то знаний совсем не хватает. Приведу реальный пример.
Имеется таблица с информацией о пациентах (ФИО, адрес, телефон и т.д.), а так же таблица с информацией об обследованиях (Врач, Дата, результат и т.д.)
Естественно что у каждого пациента может быть по несколько обследований.
Так вот мне надо составить запрос таким образом, чтобы вывести список всех пациентов, где каждая строка будет состоять из данных из первой таблицы (личная информация) + некоторые данные из второй таблицы (обследования), которые при этом являются самыми последними (т.е. актуальными).
Пример, имеется пациент, у которого 5 обследований. И только в последнем 5-ом обследовании у него была выявлена патология, поэтому в результате запроса должна фигурировать только последняя запись об обследовании, а не все. И так же со всеми остальными, включая тех у кого ещё нету записей об обследованиях. Т.е. смысл заключается в том, чтобы отобразить самую свежую информацию об состоянии дел.
28 окт 09, 12:40    [7849261]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3264
красавчег.
Начинаем читать отсюда п.4 п.6
28 окт 09, 12:43    [7849297]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
aleha
И только в последнем 5-ом обследовании у него была выявлена патология,
поэтому в результате запроса должна фигурировать только последняя запись об обследовании, а не все.
А почему это "не все"?
А если выявлена только в 4-м обследовании, а в 5-м уже почему-то не была выявлена?
Нет ли тут угрозы для жизни пациентов?
28 окт 09, 12:48    [7849357]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
--__Александр__--
Member

Откуда:
Сообщений: 2631
Как то так наверное:
SELECT * FROM Table_Пациент
LEFT JOIN
(SELECT Col1,Col2,Col3,id_пациент, 
ROW_NUMBER() OVER (PARTITION BY id_пациент ORDER BY Date_обследования DESC ) as NN
FROM Table_Обследования) as T1
 ON Table_Пациент.id_пациент = T1.id_пациент
AND NN=1
28 окт 09, 12:52    [7849393]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
--__Александр__--
Member

Откуда:
Сообщений: 2631
Паганель,

Видимо, если выявляется паталогия, до обследования уже больше не проводят, а карточку сразу передают в морг )).
28 окт 09, 12:53    [7849409]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
aleha
Member

Откуда:
Сообщений: 104
В принципе --__Александр__-- прав, если выявлена паталогия, то она уже никуда не денется, но вот дата последующего обследования будет меняться.
Сейчас попробую разобраться, в том что ты написал, а то вложенные запросы не мой конёк.
Использую SQLExpress 2008 Оболочку пишу сам на VB.
28 окт 09, 12:57    [7849453]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
aleha
В принципе --__Александр__-- прав, если выявлена паталогия, то она уже никуда не денется, но вот дата последующего обследования будет меняться.
Сейчас попробую разобраться, в том что ты написал, а то вложенные запросы не мой конёк.
Использую SQLExpress 2008 Оболочку пишу сам на VB.
Для 2008 лучьше так:
SELECT * 
FROM Table_Пациент
	CROSS APPLY (
		SELECT top 1 Col1, Col2, Col3
		FROM Table_Обследования) as T1
		WHERE Table_Пациент.id_пациент = T1.id_пациент
		ORDER BY Date_обследования DESC
	) as t
28 окт 09, 14:17    [7850183]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
aleha
Member

Откуда:
Сообщений: 104
последний код не совсем разорался со скобками поэтому удалил последнюю строку ") as t"
но результатом была лишь только 1 запись.

Предыдущий код у меня весь в ошибках, хотя постарался повторить наиболее точно. Видимо не совсем понимаю некоторые использованные в нём элементы.
28 окт 09, 15:32    [7850834]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
aleha
последний код не совсем разорался со скобками поэтому удалил последнюю строку ") as t"
но результатом была лишь только 1 запись.
Нет уж, если удалили, то будет ошибка.

Запомните Первое правило программиста - количество открывающих скобок должно равняться количеству закрывающих скобок.

Долгий путь вам ещё надо пройти :-)
28 окт 09, 15:36    [7850877]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
aleha
Member

Откуда:
Сообщений: 104
спасибо за поучительный совет, но взгляните на свой код:
автор alexeyvg

SELECT *
FROM Table_Пациент
CROSS APPLY (
SELECT top 1 Col1, Col2, Col3
FROM Table_Обследования) as T1
WHERE Table_Пациент.id_пациент = T1.id_пациент
ORDER BY Date_обследования DESC
) as t

количество скобок не равно, поэтому я и удалил последнюю строку с закрывающей скобкой.
28 окт 09, 15:39    [7850909]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
alexeyvg
Для 2008 лучьше так:
SELECT * 
FROM Table_Пациент
	CROSS APPLY (
		SELECT top 1 Col1, Col2, Col3
		FROM Table_Обследования) as T1
		WHERE Table_Пациент.id_пациент = T1.id_пациент
		ORDER BY Date_обследования DESC
	) as t
Почему-то у меня всегда устойчиво получается,
что APPLY - страшный тормоз по сравнению с JOINом.
Наверно, я не умею его готовить...
Или он-таки не "лучьше"?

Впрочем, надо пробовать для конкретного случая.
28 окт 09, 15:49    [7850992]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
aleha
спасибо за поучительный совет, но взгляните на свой код:
количество скобок не равно, поэтому я и удалил последнюю строку с закрывающей скобкой.
Ой, ошибся :-)

SELECT * 
FROM Table_Пациент
	CROSS APPLY (
		SELECT top 1 Col1, Col2, Col3
		FROM Table_Обследования as T1
		WHERE Table_Пациент.id_пациент = T1.id_пациент
		ORDER BY Date_обследования DESC
	) as t
28 окт 09, 16:27    [7851316]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
iap
Почему-то у меня всегда устойчиво получается,
что APPLY - страшный тормоз по сравнению с JOINом.
Наверно, я не умею его готовить...
Или он-таки не "лучьше"?

Впрочем, надо пробовать для конкретного случая.
Я тоже думаю, что APPLY - страшный тормоз по сравнению с JOINом. Но в данном случае простая нумерация может работать очень долго, если в Table_Обследования очень много записей. Т.е. теоретически сервер имеет возможность более оптимально построить план.

В общем, это вариант, который нужно попробовать наряду с нумерацией и сравнить планы.
28 окт 09, 16:31    [7851346]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
aleha
Member

Откуда:
Сообщений: 104
Брильянтбл!
Теперь бы ещё понять как это работает, а то CROSS APPLY пною ещё не познанны.
28 окт 09, 16:34    [7851376]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
aleha
Брильянтбл!
Теперь бы ещё понять как это работает, а то CROSS APPLY пною ещё не познанны.
Кратко:

Классический, самый простой, запрос представляет собой пересечение множеств (таблиц) по определённым условиям. Это просто JOIN

Есть ещё LEFT JOIN - с его помощью подцепляются записи, если они есть.

Подзапросы - это способ подцепить не таблицу, а результат SELECT-а

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

Эьто всё конечно очень упрощённо, особенно реляционная теория в моём изложении :-)

Примеры:

SELECT *
FROM Table1 t1
	LEFT JOIN Table2 t2 ON t2.PARENT_ID = t1.ID

SELECT *
FROM Table1 t1
	LEFT JOIN (SELECT ID, PARENT_ID FROM Table2 ) ON t2 ON t2.PARENT_ID = t1.ID

SELECT *
FROM Table1 t1
	CROSS APPLY (SELECT t2.ID, t2.PARENT_ID FROM Table2 t2 WHERE t2.PARENT_ID = t1.ID)

Результаты этих трёх запросов будут одинаковые, однако планы будут разные.
28 окт 09, 17:01    [7851616]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
aleha
Member

Откуда:
Сообщений: 104
Спасибо, начинаю понимать потихоньку.
28 окт 09, 17:11    [7851706]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить