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

Откуда:
Сообщений: 6
SELECT DISTINCT 
                      Customers.customerID AS ID, Customers.aliasID, Customers.Name, Customers.Surname, Customers.Phone, Customers.Mobile, Customers.RegDate, 
                      Orders.customerID, Orders.endDate
FROM         Customer Customers LEFT OUTER JOIN
                      ViewRepairOrders Orders ON Orders.customerID = Customers.customerID
WHERE     (Orders.endDate > '01.1.2014')
ORDER BY Customers.customerID


Все нормально выводит, но записи по customerID повторяются
А хотелось бы иметь одну строку по customerID с условием из второй таблички
3 авг 14, 18:44    [16393381]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7868
Двух одинаковых записей при DISTINCT в результате быть не может.
3 авг 14, 18:52    [16393396]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
WHERE     (Orders.endDate > '01.1.2014')
делает LEFT JOIN Orders бессмысленным (равным JOINу)
3 авг 14, 18:54    [16393399]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
iap
WHERE     (Orders.endDate > '01.1.2014')

делает LEFT JOIN Orders бессмысленным (равным JOINу)
Если не обращать внимания на нестандартный строковый формат даты.

P.S. DISTINCT оставляет по одной записи из совпадающих по ВСЕМ полям записей результата запроса,
а не только по customerID
3 авг 14, 18:57    [16393404]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Domiurg
Member

Откуда:
Сообщений: 6
Владислав Колосов
Двух одинаковых записей при DISTINCT в результате быть не может.


Так и я так думал, но что-то не доганяю

Картинка с другого сайта.
3 авг 14, 19:01    [16393408]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Domiurg
Member

Откуда:
Сообщений: 6
iap
iap
WHERE     (Orders.endDate > '01.1.2014')

делает LEFT JOIN Orders бессмысленным (равным JOINу)
Если не обращать внимания на нестандартный строковый формат даты.

P.S. DISTINCT оставляет по одной записи из совпадающих по ВСЕМ полям записей результата запроса,
а не только по customerID


Вот... Теперь и я понял

А мне нужно отобрать из первой таблички только те записи, которые есть во второй табличке, но ограниченные по дате

В терминах задачи - отобрать всех клиентов, которые обслуживались за текущий год
3 авг 14, 19:05    [16393414]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Domiurg
Member

Откуда:
Сообщений: 6
Вроде как так получилось то что надо

SELECT DISTINCT 
                      Orders.customerID, Customers.customerID AS ID, Customers.aliasID, Customers.Name, Customers.Surname, Customers.Phone, Customers.Mobile, Customers.RegDate
FROM         ViewRepairOrders Orders LEFT OUTER JOIN
                      Customer Customers ON Orders.customerID = Customers.customerID
WHERE     (Orders.endDate > '01.1.2014')
ORDER BY Orders.customerID
3 авг 14, 19:19    [16393436]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7868
Уберите записи из таблицы ORDERS... Даты окончания разные, они мешают. Или агрегируйте эти даты в min() или max().
3 авг 14, 19:23    [16393439]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
mrGuest
Guest
Domiurg,

SELECT top(1) with ties -- вместо DISTINCT
                      Customers.customerID AS ID, Customers.aliasID, Customers.Name, Customers.Surname, Customers.Phone, Customers.Mobile, Customers.RegDate, 
                      Orders.customerID, Orders.endDate
FROM         Customer Customers JOIN -- вместо бессмысленного LEFT JOIN
                      ViewRepairOrders Orders ON Orders.customerID = Customers.customerID
WHERE     (Orders.endDate > '01.1.2014')
ORDER BY row_number() over (partition by Customers.customerID order by Orders.endDate desc) -- вместо просто сортировки 
4 авг 14, 09:24    [16394268]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
o-o
Guest
логичнее не соединять, а использовать exists.
т.е. выборка from customer c
where exists (select * from ViewRepairOrders o where o.customerID = c.customerID 
      and o.endDate > '20140101')  -- "обслуживались за текущий год", 
и не надо будет никакой distinct лепить
4 авг 14, 11:54    [16395022]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
mrGuest
Guest
o-o
логичнее не соединять, а использовать exists.
т.е. выборка from customer c
where exists (select * from ViewRepairOrders o where o.customerID = c.customerID 
      and o.endDate > '20140101')  -- "обслуживались за текущий год", 
и не надо будет никакой distinct лепить


1. Так тоже можно, но в исходном запросе автора выводилась дата заказа, возможно она ему нужна.
2. "select *" - это Вас кто так научил писать? Бросьте немедленно.
3. Подзапросы тоже надо использовать с осторожностью - могут сильно замедлить выполнение (не конкретно про этот случай).
4 авг 14, 13:05    [16395458]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
mrGuest
2. "select *" - это Вас кто так научил писать? Бросьте немедленно.
SELECT * в EXISTS() - это нормально. Общепринятая практика.
Хотя там можно писать почти всё, что угодно. Это неважно.
4 авг 14, 13:11    [16395486]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
o-o
Guest
mrGuest
2. "select *" - это Вас кто так научил писать? Бросьте немедленно.


ну уж точно не mrGuest учил :)
приведу цитату уважаемого мной автора по этому поводу
а соглашаться ли с Ициком Бен-Ганом или с mrGuest-ом -- личное дело каждого

Unlike most other cases, in this case it’s logically not a bad practice to use an asterisk (*) in the SELECT
list of the subquery in the context of the EXISTS predicate
. The EXISTS predicate only cares
about the existence of matching rows regardless of the attributes specified in the SELECT list, as if the
whole SELECT clause were superfluous. The SQL Server database engine knows this, and in terms of
optimization, ignores the subquery’s SELECT list. So in terms of optimization, specifying the column
wildcard * in this case has no negative impact when compared to alternatives such as specifying a constant.

However, some minor extra cost might be involved in the resolution process of expanding the
wildcard against metadata info. But this extra resolution cost is so minor that you will probably barely
notice it. My opinion on this matter is that queries should be natural and intuitive, unless there’s a very
compelling reason to sacrifice this aspect of the code. I find the form EXISTS(SELECT * FROM . . .) much
more intuitive than EXISTS(SELECT 1 FROM . . .). Saving the minor extra cost associated with the resolution
of * is something that is not worth the cost of sacrificing the readability of the code
.
4 авг 14, 13:23    [16395577]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
mrGuest
Guest
Для exists я согласен :)
Но думаю, что лучше придти к такому написанию осознанно (при желании), когда не имеешь привычки писать везде и всюду "select *", и знаешь почему это плохо.
А покажи новичку в SQL, что так можно писать и он ведь так и будет писать, потому что лень, а не по религиозным соображениям.
4 авг 14, 13:51    [16395780]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Glory
Member

Откуда:
Сообщений: 104760
mrGuest
Но думаю, что лучше придти к такому написанию осознанно (при желании),

К этому надо "придти" через чтение хелпа. В котором производителм ясно написал

Notice that subqueries that are introduced with EXISTS are a bit different from other subqueries in the following ways:
- The keyword EXISTS is not preceded by a column name, constant, or other expression.
- The select list of a subquery introduced by EXISTS almost always consists of an asterisk (*). There is no reason to list column names because you are just testing whether rows that meet the conditions specified in the subquery exist.

ЗЫ
"Городская легенда" 1 лучше, чем * была правдой для теперь уже древних версий MSSQL.
4 авг 14, 13:57    [16395829]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7868
Эта легенда бьёт все рекорды по-моему :)
Ни у одного фаната этой идеи не хватило, не знаю чего, просто проверить план запроса.

select * в общем случае имело и имеет смысл, необходимо лишь понимать последствия.
4 авг 14, 14:09    [16395929]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Shakill
Member

Откуда: мск
Сообщений: 1880
в одном случае звезду просто не получится написать физически и всё-таки придется использовать SELECT 1
create view dbo.Test
with schemabinding
as
	select 'yes'
	where exists(select * from sys.objects)
Msg 1054, Level 15, State 6, Procedure Test, Line 5
Syntax '*' is not allowed in schema-bound objects.
4 авг 14, 14:21    [16395997]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Glory
Member

Откуда:
Сообщений: 104760
Shakill
в одном случае звезду просто не получится написать физически

Как будто в таком представлении только в части exists нельзя написать *
4 авг 14, 14:26    [16396025]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Shakill
Member

Откуда: мск
Сообщений: 1880
Glory
Shakill
в одном случае звезду просто не получится написать физически

Как будто в таком представлении только в части exists нельзя написать *
но для exists() могли бы это ограничение не учитывать. видимо, выбор был сделан в пользу простоты парсера
4 авг 14, 14:44    [16396152]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
Glory
Member

Откуда:
Сообщений: 104760
Shakill
Glory
пропущено...

Как будто в таком представлении только в части exists нельзя написать *
но для exists() могли бы это ограничение не учитывать. видимо, выбор был сделан в пользу простоты парсера

А в команде CREATE TABLE вообще select нельзя написать, хоть со звездой, хоть без. И что ?
4 авг 14, 14:47    [16396165]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом новичку...  [new]
o-o
Guest
по поводу всевозможных домыслов есть отличная сказочка
вроде дело было куда проще, чем create view with schemabinding

да, я тоже думаю, лень им было выцеплять основной селект,
поэтому и подзапрос тоже на предмет звезды шерстит.
но прикольно: если в основной селект зафигасить '*' (как строку, в кавычках, ну мало-ли, для красоты вывода),
то такую закавыченную звезду пропускает
4 авг 14, 14:51    [16396188]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить