Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
kombala Member Откуда: Сообщений: 41 |
Есть такая проблема, в таблицах справочников к услугам привязаны факторы и услуга может быть либо обязательной, либо необязательной, но при выполнении определенного условия тоже становится обязательной. Грубо говоря, если у клиента А есть несколько факторов и в первом факторе имеется услуга_1, а во втором факторе имеется услуга_1_с_условием и клиент это условие проходит, то выводится две строки: услуга_1 | id_клиента услуга_1_с_условием | id_клиента В таком случае нужно что-бы выводилась только 1 из этих двух услуг. Не могу придумать, как это можно написать, т.к. просто в where ограничить нельзя, потому что есть клиенты которые проходят только по усл._1, есть которые проходят только по усл._1_с_усл., а вот есть те, у которых оба значения выводятся и именно с этим получается косяк, т.к. цифры задваиваются и на итог получается, что результат скрипта больше чем было собственно самих клиентов. В идеале конечно нужно править справочник, но его создавали задолго до меня и там под 10'000 строк, а скрипт рабочий нужен сейчас. Прошу вашей помощи, извините если криво пересказал суть проблемы. |
23 июн 17, 15:19 [20586342] Ответить | Цитировать Сообщить модератору |
Akina Member Откуда: Зеленоград, Москва, Россия Сообщений: 20970 |
Группировка по клиенту и MIN (или MAX) для вывода нужной. Другой вариант - первая выборка строго без условия, вторая строго с условием, LEFT JOIN первого ко второму и сборка через COALESCE. |
23 июн 17, 15:24 [20586356] Ответить | Цитировать Сообщить модератору |
kombala Member Откуда: Сообщений: 41 |
Akina, на каждого клиента свой список услуг в котом может быть до двух десятков наименований, которые подбираются исходя из факторов клиента, поэтому min / max не подходит. А вот COALESCE погуглил, вроде бы то, что нужно, спасибо. |
23 июн 17, 15:48 [20586434] Ответить | Цитировать Сообщить модератору |
Serп
Guest |
kombala, Тогда, может быть, табличную функцию, которая для клиента выдает услуги, согласно всем факторам и через apply соединять? |
23 июн 17, 15:52 [20586446] Ответить | Цитировать Сообщить модератору |
kombala Member Откуда: Сообщений: 41 |
Serп, извините, а можно еще раз для дебила? Я просто с SQL второй месяц работаю, еще многого не знаю. Табличная форма и соединять через apply - это как? Если можно, то с примером. |
23 июн 17, 15:56 [20586466] Ответить | Цитировать Сообщить модератору |
Руслан Дамирович Member Откуда: Резиновая нерезиновая Сообщений: 940 |
Извини, если криво, но я бы это сделал так. WITH s AS ( SELECT c.[id_client], ss.[service], [rn] = ROW_NUMBER() OVER ( PARTITION BY c.[id_client], CASE WHEN s.[somewhere] = 'somehow' THEN 1 WHEN s.[somewhere] = 'somehow2' THEN 2 ELSE 999 END ) FROM clients c LEFT JOIN [services] s ON ( s.[id_client] = c.[id_client] ) ) SELECT [id_client], [service] FROM s WHERE [rn] = 1 |
||
23 июн 17, 16:09 [20586504] Ответить | Цитировать Сообщить модератору |
Руслан Дамирович Member Откуда: Резиновая нерезиновая Сообщений: 940 |
[rn] = ROW_NUMBER() OVER ( PARTITION BY c.[id_client] ORDER BY CASE WHEN s.[somewhere] = 'somehow' THEN 1 WHEN s.[somewhere] = 'somehow2' THEN 2 ELSE 999 END ) |
23 июн 17, 16:13 [20586525] Ответить | Цитировать Сообщить модератору |
Serп
Guest |
kombala, Табличная функция - это функция, результатом работы которой является таблица. В вашем случае функция по id клиента возвращает все услуги, которые ему положены (проверяя все сопутствующие факторы). Ну и далее запрос вида: Select c.Id, s.service from dbo.clients c outer apply dbo.Function(c.id) s Мне кажется, как-то так будет проще... |
23 июн 17, 16:15 [20586534] Ответить | Цитировать Сообщить модератору |
dies irae Member Откуда: Сообщений: 78 |
неплохо, order by правда забыл и можно чуть лаконичнее: select c.* ,s.* from clients as c outer apply ( select top(1) with ties s.* from services as s where s.client_id = c.id order by row_number() over (partition by s.client_id order by case when s.[somewhere] = 'somehow' then 1 when s.[somewhere] = 'somehow2' then 2 else 999 end ) ) as c |
||
23 июн 17, 17:12 [20586733] Ответить | Цитировать Сообщить модератору |
aleks2
Guest |
1. Либо в основном справочнике , либо доп. справочник колбасите Эквивалентные услуги (У1, У2) 2. Разучиваете not exists |
||
24 июн 17, 09:27 [20587796] Ответить | Цитировать Сообщить модератору |
kombala Member Откуда: Сообщений: 41 |
Всем большое спасибо за помощь. |
26 июн 17, 14:55 [20590854] Ответить | Цитировать Сообщить модератору |
kombala Member Откуда: Сообщений: 41 |
Руслан Дамирович, не знал, что можно делать кейсы внутри row_number, классно! |
26 июн 17, 14:57 [20590864] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |