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

Откуда:
Сообщений: 6
Добрый день.
Ткните пожалуйста меня носом - как сделать эту задачу красиво ?
Роюсь уже 3 дня, хотя вроде на вид не шибко сложная..

5. Покупатель имеет бонусную карту, привязанную только к его номеру телефона.
Покупатель может заменить бонусную карту по причине утери, либо какой-то другой.
При этом все данные со старой карты клонируются на новую, включая номер телефона, а старая очищается. После этого старая карта считается свободной для следующей выдачи либо замены (переноса данных). Поскольку покупатель всегда имеет право поменять номер телефона и перепривязать бонусную карту к нему, идентифицируем покупателя на текущий момент как владельца той или иной бонусной карты.
Один покупатель не имеет права осуществлять более 5 переносов с карты на карту в год (@limit = 5).
Есть процедура замены, получающая на вход два номера карты – текущий (@old_card) и новый (@new_card).
Требуется написать скрипт для нее, определяющий, позволяется ли покупателю осуществить текущий перенос (достиг ли он лимита), если лимит достигнут, когда он сможет в следующий раз воспользоваться заменой карты.
Есть таблица переносов c карты на карту:

Table cards_transfer
old_card new_card dt
111 555 2020-01-09
222 223 2020-02-10
333 334 2020-03-11
444 222 2020-04-12
555 666 2020-05-12
666 777 2020-06-13
777 888 2020-07-14
888 000 2020-08-15
999 333 2020-09-16
223 111 2020-10-16
Таким образом, согласно данным в примере, владелец карты 000 не может осуществлять замену карты до 09.01.2021.

Сообщение было отредактировано: 9 июн 21, 17:53
9 июн 21, 17:59    [22333460]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Кесарь
Member

Откуда:
Сообщений: 651
grabli092,

копать надо в сторону "родители" и "рекурсия".

Что-то вроде такого (код не мой, поэтому такой вид):

;WITH relationships AS (
   SELECT *,  1 as n
   FROM Table
   WHERE Child = 'A' -- стартовая позиция
   UNION ALL
   SELECT p.*, n + 1   -- количество актов наследования
   FROM Table p
    JOIN relationships pa on pa.Child = p.Parent  -- правило соединения для след. шага
) 
select *
from relationships 
where n > 5 ;


Сообщение было отредактировано: 9 июн 21, 18:11
9 июн 21, 18:18    [22333479]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
grabli092
Member

Откуда:
Сообщений: 6
Кесарь,
мне кажется я вроде понял, буду рыть тут.. спасибо в любом случае

Сообщение было отредактировано: 9 июн 21, 18:18
9 июн 21, 18:25    [22333483]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Кесарь
Member

Откуда:
Сообщений: 651
grabli092
Кесарь, про "родителей" это в смысле ДНК ? )) или я не понял аллегорию ?
насчет своего ДНК я и не обольщаюсь вовсе. Почему то всегда хожу самыми извилистыми путями и через заборы.. это у меня с рождения ((


Где, где смайлик "рукалицо"???


grabli092, это профессиональный форум. Здесь выражаются не аллегорически. Если я сказал вам искать по словам "родители" и "рекурсия", то так и ищите. Не забудьте вначале написать "sql server".

Если не нравится так, то ищите "обход дерева наследования". Но там будет больше не нужных вам вариантов...
9 июн 21, 18:29    [22333485]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
grabli092
Member

Откуда:
Сообщений: 6
Кесарь,
нененене.. мне все нравится... мне просто нужен был пинок толчок в нужную сторону, я очень ценю помощь

Сообщение было отредактировано: 9 июн 21, 19:02
9 июн 21, 19:10    [22333505]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
SERG1257
Member

Откуда:
Сообщений: 2863
При фискированном уровне вложений можно сделать пять left join.
Запрос будет проще, накосячить сложнее чем с рекурсией.
9 июн 21, 19:58    [22333523]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Кесарь
Member

Откуда:
Сообщений: 651
SERG1257
При фискированном уровне вложений можно сделать пять left join.
Запрос будет проще, накосячить сложнее чем с рекурсией.


Задача не найти пять родителей, а найти того, у кого уже 5 или более (в любой системе бывают косяки, у кого-то может уже 6).

И потом, если бизнес решит поменять кол-во смен карт за год, вы переписывать код будете?



Нормальные программисты (инженеры) хранят бизнес-настройки в том или ином виде, доступном для редактирования пользователями бизнеса. И применяют эти настройки в коде в виде переменных. В результате чего почти никогда не требуется переделка кода при изменении параметров (остаток случаев запишем на снифинг).

Если вы делаете не так, то переучивайтесь на нормальный способ ведения дел.
10 июн 21, 11:35    [22333658]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 21178
SERG1257
При фискированном уровне вложений можно сделать пять left join.
LEFT-то зачем? INNER хватит. Если запрос вернул пустой набор - можно менять. Если не пустой - смотрим дату из 5-й копии.

Кесарь
Что-то вроде такого
Отсечку надо делать во WHERE рекурсивной части - нафига нужна вся цепь обменов?

PS. А ещё в запрос следует добавить проверку, что переданный номер карты является конечным. А то так можно прийти с якобы утраченной ранее картой - и вот уже у тебя две бонусные карты.

Сообщение было отредактировано: 10 июн 21, 12:18
10 июн 21, 12:24    [22333695]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Кесарь
Member

Откуда:
Сообщений: 651
Akina
SERG1257
При фискированном уровне вложений можно сделать пять left join.
LEFT-то зачем? INNER хватит. Если запрос вернул пустой набор - можно менять. Если не пустой - смотрим дату из 5-й копии.

Кесарь
Что-то вроде такого
Отсечку надо делать во WHERE рекурсивной части - нафига нужна вся цепь обменов?


Хотя тоже стратегия, особенно эффективна на самописных системах: всегда будет работа. Ведь столько нужно переделывать, а ты такой незаменимый...

В предпенсионном возрасте особенно полезно.
10 июн 21, 12:28    [22333698]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
uaggster
Member

Откуда:
Сообщений: 1030
Кесарь
SERG1257
При фискированном уровне вложений можно сделать пять left join.
Запрос будет проще, накосячить сложнее чем с рекурсией.


Задача не найти пять родителей, а найти того, у кого уже 5 или более (в любой системе бывают косяки, у кого-то может уже 6).

Значит, нужно сделать 6 left join'ов
И потом, если бизнес решит поменять кол-во смен карт за год, вы переписывать код будете?

Нормальные программисты (инженеры) хранят бизнес-настройки в том или ином виде, доступном для редактирования пользователями бизнеса. И применяют эти настройки в коде в виде переменных. В результате чего почти никогда не требуется переделка кода при изменении параметров (остаток случаев запишем на снифинг).

Если вы делаете не так, то переучивайтесь на нормальный способ ведения дел.

Ага. Руками.
Я не хочу сказать, что вариант с рекурсией - очень сложный, я бы тоже, например так и сделал.
Но вызов подобного запроса обязательно должен предваряться либо проверкой хранящихся значений в таблице на наличие петель, либо с ограничением на глубину рекурсии.
А кондовый способ с 6 лефт джойнами - ничего такого не требует. Он прост, как лом и такой же прочный и неломаемый.
И, как показывает практика - чем проще, тупее и очевиднее код - тем лучше.
10 июн 21, 12:31    [22333700]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Кесарь
Member

Откуда:
Сообщений: 651
Akina
Кесарь
Что-то вроде такого
Отсечку надо делать во WHERE рекурсивной части - нафига нужна вся цепь обменов?

PS. А ещё в запрос следует добавить проверку, что переданный номер карты является конечным. А то так можно прийти с якобы утраченной ранее картой - и вот уже у тебя две бонусные карты.


1. Если рассматривать задачу узко, то да. А если заботится о системе в целом, то при получении значения N более 5-ти можно и нужно формировать сообщение об ошибке процесса и отсылать его через обмен в нужное место для разбора.

2. Вот тут не могу не согласиться!
10 июн 21, 12:33    [22333702]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Кесарь
Member

Откуда:
Сообщений: 651
uaggster
Кесарь
пропущено...


Задача не найти пять родителей, а найти того, у кого уже 5 или более (в любой системе бывают косяки, у кого-то может уже 6).

Значит, нужно сделать 6 left join'ов
И потом, если бизнес решит поменять кол-во смен карт за год, вы переписывать код будете?

Ага. Руками.

И, как показывает практика - чем проще, тупее и очевиднее код - тем лучше.


Вы очень оригинально понимаете смысл автоматизации...



Касательно проверок: само собой, я ведь не говорил, что мой код конечен. Это был пример куда копать, не более. Но он позволяет делать автоматизацию. А "лефт джойны в штуках" нет.

В нормальной системе у менеджера есть возможность поменять значение параметра руками в клиенте. И это сразу и автоматически будет иметь силу. Без какой либо переделки в системе.
10 июн 21, 12:39    [22333707]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
uaggster
Member

Откуда:
Сообщений: 1030
Кесарь

Вы очень оригинально понимаете смысл автоматизации...

Ага. Только не оригинально, а единственно правильное, я бы сказал.
Программа, в идеале, должна а) Работать б) Быть обслуживаемой. Причем крайне желательно - программистом (джуниором) "с улицы", через 5 минут после вхождения в тему.
Ergo - чем тупее и железобетоннее код - тем лучше.
Программы пишутся для программистов, а не для компьютеров.
Изящные, "конфигурируемые" и "свободно настраиваемые" и тому подобные решения - не работают от слова "совсем".
Там, где можно обойтись ломом - там избыточен даже перфоратор.

И да. Не нужно делать хорошо. Нужно делать - чтобы работало. Ударение на "работало".

Касательно проверок: само собой, я ведь не говорил, что мой код конечен. Это был пример куда копать, не более. Но он позволяет делать автоматизацию. А "лефт джойны в штуках" нет.

На самом деле - тоже позволяют.
Надо сделать один join и While не более 6 раз или до получения пустого резалтсета.
(я бы так не сделал (а сделал бы рекурсией), но это как раз было бы максимально устойчивым и при этом конфигурируемым решением).

Сообщение было отредактировано: 10 июн 21, 12:52
10 июн 21, 13:01    [22333736]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
uaggster
Member

Откуда:
Сообщений: 1030
Кесарь, Да, кстати, забыл "Касательно проверок".
В абсолютном идеале - код не должен требовать проверок. "Проверка" - должна быть имманентна самому коду.
Вот 6 лефт джойнов - не чувствительны к качеству данных и проверок на петли - не требуют. Совсем.
Следовательно - в системе в принципе невозможны ошибки функционирования, связанные с а) качеством данных в системе (которые всегда говно, и по-другому не бывает) и с б) с реализацией самих проверок (которые пишутся людьми, у которых всегда руки не из того места, и по другому - тоже не бывает).

Хотя я тоже выберу вариант с рекурсией. Он первым приходит на ум. :-)
10 июн 21, 13:07    [22333743]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8690
Решение зависит от контекста задачи и контекста исполнения. При массовой обработке рекурсии могут сесть на попу, в этом случае джойны более выгодны. Если абонент меняет карту на карту по кругу, рекурсия сломается, а ему не запрещено это делать.
10 июн 21, 13:27    [22333770]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
invm
Member

Откуда: Москва
Сообщений: 9772
uaggster
Хотя я тоже выберу вариант с рекурсией. Он первым приходит на ум. :-)
Рекурсия почти всегда слишком дорогое удовольствие.
Задача ТС решается гораздо проще - дополнительный столбец, хранящий корневую карту для цепочки.
10 июн 21, 13:34    [22333776]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
Focha
Member

Откуда: Москва
Сообщений: 597
оО знакомое задание, не помню только в какой конторе оно было :(
10 июн 21, 13:38    [22333784]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
aleks222
Member

Откуда:
Сообщений: 1414
invm
uaggster
Хотя я тоже выберу вариант с рекурсией. Он первым приходит на ум. :-)
Рекурсия почти всегда слишком дорогое удовольствие.
Задача ТС решается гораздо проще - дополнительный столбец, хранящий корневую карту для цепочки.


Еще проще, оно решается наличием идентификатора клиента в этих бредовых данных.
10 июн 21, 14:45    [22333859]     Ответить | Цитировать Сообщить модератору
 Re: тестовая задача - с какой стороны рыть ?  [new]
uaggster
Member

Откуда:
Сообщений: 1030
aleks222
invm
пропущено...
Рекурсия почти всегда слишком дорогое удовольствие.
Задача ТС решается гораздо проще - дополнительный столбец, хранящий корневую карту для цепочки.


Еще проще, оно решается наличием идентификатора клиента в этих бредовых данных.

Да он есть. Это номер телефона, как я понял. Просто нам привязку карты к телефону - не показали.
10 июн 21, 14:54    [22333866]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить