Раді Вас бачити! » Увійти » Створити новий профіль

ФЗВ: Помогите с SQL запросом-6 (або задачка на співбесіді яку я не вирішив)

Була в мене співбесіда, вже не памятаю в яку канторку, років з 10 назад ...
три теоретичних питання і три задачки на селекти які тре було написати на листочку бумаги.

все зробив там по теорії щось про рівні ізоляцій транзакцій, по індексам  а останню задачку не рішив.
Потім дома десь в 2-3 ночі її таки написав ...

Задачка наступна
є одна таблиця з  полями
ID   DATA
1    2013-05-06
2    2012-12-26
3    2011-07-07

Потрібно написати одним слектом який би вертав до кожного запису в таблиці дату осаннього четверга місяця в котрому та дата

ID   DATA            RESULT
1    2013-05-06   2013-05-29 (останній четвер місяця)
2    2012-12-26   ...
3    2011-07-07   ...

П.С. База MS SQL
 



Останнє редагування: 28 жовтня 2018 18:49:19 від pravda
   
получить день недели первого числа
используя полученную поправку получить дату последнего четверга

   
ну и не забыть про февраль на всякий случай
   
получить день недели первого числа
используя полученную поправку получить дату последнего четверга

так але тоді не зробив одним запитом на листочку паперу :-)
   
так але тоді не зробив одним запитом на листочку паперу :-)
если бы мне предложили такое делать "на листочке бумаги", я бы поблагодарил за потраченое время и ушел
   
Якщо хто хоче і напише зараз один селект із студентів чи молодих та амбіційних .
Обіщаю що рекомендую на передостаннє місце своєї роботи. Вони якраз шукають молодого спеціаліста по БД. Мене недавно запитували чи не можу кого їм порекомендувати.
м.Київ

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

та я был зеленым, наивным и напуганным :-)
   
Була в мене співбесіда, вже не памятаю в яку канторку, років з 10 назад ...
три теоретичних питання і три задачки на селекти які тре було написати на листочку бумаги.
все зробив там по теорії щось про рівні ізоляцій транзакцій, по індексам  а останню задачку не рішив.
Потім дома десь в 2-3 ночі її таки написав ...

Задачка наступна
є одна таблиця з  полями
ID   DATA
1    2013-05-06
2    2012-12-26
3    2011-07-07

Потрібно написати одним слектом який би вертав до кожного запису в таблиці дату осаннього четверга місяця в котрому та дата

ID   DATA            RESULT
1    2013-05-06   2013-05-29 (останній четвер місяця)
2    2012-12-26   ...
3    2011-07-07   ...

П.С. База MS SQL

Якби мені на співбесіді запропонували почати розв"язувати усяку подібну іксню на папірцю, я б подумав, що у цій "конторці" чокнуті працюють і відкинув б це місце, як кандидата на моє працевлаштування.
   
На інтерна пробувався?

та вже не памятаю, але задачка запамяталась ...
   
если бы мне предложили такое делать "на листочке бумаги", я бы поблагодарил за потраченое время и ушел
+
Отожбойвоно
   
А щоб довго не заморачуватись, то щось таке

select id, data,
case datepart(weekday, eomonth(data))
when 1 then dateadd(day,-3,eomonth(data))
when 2 then dateadd(day,-4,eomonth(data))
when 3 then dateadd(day,-5,eomonth(data))
when 4 then dateadd(day,-6,eomonth(data))
when 5 then eomonth(data)
when 6 then dateadd(day,-1,eomonth(data))
else dateadd(day,-2,eomonth(data))
end as lastThursdayOfMonth
from table
   
Якби мені на співбесіді запропонували почати розв"язувати усяку подібну іксню на папірцю, я б подумав, що у цій "конторці" чокнуті працюють і відкинув б це місце, як кандидата на моє працевлаштування.
Жаль, значит вьі откажитесь работать в Google. Тут предлагают решать задачки у доски  :weep:
   
Жаль, значит вьі откажитесь работать в Google. Тут предлагают решать задачки у доски  :weep:

Якщо Гуглю мене потрібно буде, хай стає у чергу  :gigi:
   
Жаль, значит вьі откажитесь работать в Google. Тут предлагают решать задачки у доски  :weep:
вот шото мне подсказывает что там не гугл был
   
Чи потрібно в голові тримати назви всіх функцій роботи з датами?
   
Схема проста
У місяцях різна кількість днів. Тож треба танцювати від кінця місяця. Визначаємо останній день місяця, його номер у тижні, і відступаємо до найближчого четвертого дня тижня

Старий MSSQL (до 2012)

Код: [Select]
SELECT
    [id],
    [date],
    [last_date],
    DATEADD(d, 4 - DATEPART(dw, [last_date]) - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END, [last_date]) AS [last_thursday]
FROM (
    SELECT
[id],
[date],
CAST(DATEADD(d,-1, DATEADD(mm, DATEDIFF(m,0,[date])+1,0)) AS DATE) AS [last_date]
    FROM #test
) ps;


Новий

Код: [Select]
SELECT
    [id],
    [date],
    [last_date] ,
    DATEADD(d, 4 - DATEPART(dw, [last_date]), [last_date] - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END) AS [last_thursday]
FROM (
    SELECT
[id],
[date],
EOMONTH([date]) AS [last_date]
    FROM #test
) ps;


Останнє редагування: 15 серпня 2018 09:31:12 від H.Kropp
   
да, если считать от последнего дня, то код будет короче
   
вот шото мне подсказывает что там не гугл был

та який нах гугл, якась канторка в києві в районі ДВРЗ десь на території якогось радянського НДІ чи заводу, на прохідні ще якийсь пенс сидів і по паспорту пропуск талончик виписував  :laugh:
   
Схема проста
У місяцях різна кількість днів. Тож треба танцювати від кінця місяця. Визначаємо останній день місяця, його номер у тижні, і відступаємо до найближчого четвертого дня тижня

Старий MSSQL (до 2012)

Код: [Select]
SELECT
    [id],
    [date],
    [last_date],
    DATEADD(d, 4 - DATEPART(dw, [last_date]) - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END, [last_date]) AS [last_thursday]
FROM (
    SELECT
[id],
[date],
CAST(DATEADD(d,-1, DATEADD(mm, DATEDIFF(m,0,[date])+1,0)) AS DATE) AS [last_date]
    FROM #test
) ps;

Новий

Код: [Select]
SELECT
    [id],
    [date],
    [last_date] ,
    DATEADD(d, 4 - DATEPART(dw, [last_date]), [last_date] - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END) AS [last_thursday]
FROM (
    SELECT
[id],
[date],
EOMONTH([date]) AS [last_date]
    FROM #test
) ps;

Datepart дає четвер як 5-ий день, мені здається.
То ж англосакси, у них неділя - перший день тижня, а не понеділок.
   
Чи потрібно в голові тримати назви всіх функцій роботи з датами?
Дякуючи гуглу - не обов'язково :)
Досить знати, що такі функції існують.
   
Якщо хто хоче і напише зараз один селект із студентів чи молодих та амбіційних .
Обіщаю що рекомендую на передостаннє місце своєї роботи. Вони якраз шукають молодого спеціаліста по БД. Мене недавно запитували чи не можу кого їм порекомендувати.
м.Київ
Знаючи тебе, що ти задницею відчуває неприємності і звідти втік, то від тої фірмочки краще триматись подалі.
   
Знаючи тебе, що ти задницею відчуває неприємності і звідти втік, то від тої фірмочки краще триматись подалі.

Пішов я звідти по двум причинам.

1 Зарплатня без привязки до доллара. Хоча була на рівні і біла. А я собі поставив за мету був незалежати від постійної девальвації гривні.

2. Я прагнув змінити спеціалізацію з прогр. БД на пайтон дева. А там такої позиції не було.

А фірмочка і далі працює і доволі успішна. З повним соцпакетом, медстраховкою і інш.
Я з великим задоволенням туда захожу в гості як буваю в Києві.



   
Якщо Гуглю мене потрібно буде, хай стає у чергу  :gigi:
:
(tu)
   
Datepart дає четвер як 5-ий день, мені здається.
То ж англосакси, у них неділя - перший день тижня, а не понеділок.

ну не розписувати ж до останньої коми

SET DATEFIRST 1;
   
ну не розписувати ж до останньої коми

SET DATEFIRST 1;

Почитав про DATEFIRST, щоб освіжити. Треба пильним з ним бути, бо

The setting of SET DATEFIRST is set at execute or run time and not at parse time.

Specifying SET DATEFIRST has no effect on DATEDIFF. DATEDIFF always uses Sunday as the first day of the week to ensure the function is deterministic.
   
P.D. Спробував Вашу query, H. Kropp
Працює. (tu)
Правда ось це:
[last_date] - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END
не катить, бо last_date це datetime і при арифметичній операції кидає помилку Type Mismatch.
Тобто треба використати щось таке
DATEADD(d, 4 - DATEPART(dw, [last_date]), dateadd(d, CASE WHEN DATEPART(dw, [last_date]) < 4 THEN -7 ELSE 0 END,[last_date])) AS [last_thursday]
   
Там у мене помилка
Тре

DATEADD(d, (4 - DATEPART(dw, [last_date]) - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END), [last_date]) AS [last_thursday]

Останнє редагування: 15 серпня 2018 17:34:55 від H.Kropp
   
Там у мене помилка
Тре

DATEADD(d, (4 - DATEPART(dw, [last_date]) - CASE WHEN DATEPART(dw, [last_date]) < 4 THEN 7 ELSE 0 END), [last_date]) AS [last_thursday]

а чи можна знайти цю дату без умовної функції?
   
Якщо б така задача була реальна, то я б просто завів окрему таблицю всіх четвергів кожного місяця і джойнив би.  Одним дуже коротким, дуже простим селектом. Було б практично і maintainable.

Якщо так не хочеться, то це просто задача на конвертацію дати засобами вбудованих в SQL функцій, просто задача на знання довідника, і тоді це дуже дурне запитання. Навіщо запам'ятовуваті довідник функцій?
   
Якщо б така задача була реальна, то я б просто завів окрему таблицю всіх четвергів кожного місяця і джойнив би.  Одним дуже коротким, дуже простим селектом. Було б практично і maintainable.
нуфу!
Детальнее пояснять? :)
   
нуфу!
Детальнее пояснять? :)

Будь ласка ;)

Я думаю, що ціна такого рішення дуже невелика, код буде дуже простий, дуже важко зробити помилку при всяких майбутніх змінах. По швидкості скоріш за все ні на що не впливає, якщо це тільки не в якомусь внутрішньому циклі.  Таблиця з четвергами також майже нічого не коштує. (Це практично як без SQL в звичайному коді задати констатами).
   
Дивіться, скільки всього останніх четвергів місяця? Стільки ж, скільки місяців. 12 на рік.  Просто перелік всіх таких дат за декілька років займе менше місця, ніж деякі запити на попередній сторінці.

Практичний software engineering відрізняється від задачок на папірці на співбесіді тим, що рішення мають бути максиально прагматичними і простими, щоб могла розібратися навіть людина, яка не така розумна, в перший раз бачить цей код, не до кінця розуміє задачу, і взагалі проходила поруч просто ;)   І це особливо правда саме в тих великих компаніях, які люблять дуже розумні запитання на папірцях на співбесідах :)
   
Будь ласка ;)

Я думаю, що ціна такого рішення дуже невелика, код буде дуже простий, дуже важко зробити помилку при всяких майбутніх змінах. По швидкості скоріш за все ні на що не впливає, якщо це тільки не в якомусь внутрішньому циклі.  Таблиця з четвергами також майже нічого не коштує. (Це практично як без SQL в звичайному коді задати констатами).

Сорри, пропустил
в данном конкретном случае, т.к. результирующий набор данных описывается простым условием, то лучше использовать вычисление, чем добавлять дополнительную таблицу и джойн
в принципе, "ничего страшного", и, наверное, в конкретном случае - "и так сойдёт", но каждый дополнительный джойн - это нагрузка на оптимизатор и машину выполнения запросов
тоже вроде ничего страшного, но когда запросы разрастаются....
в общеем - принцип KISS имеет место быть

но, опять таки - it depends
во многих случаях выгодно сделать более простой алгоритм с лишней таблицей/джойном, чем заморачивать себя и будущего разработчика "хирым вывихом", в котором еще и разбираться надо будет

так что я говорю "нуфу!", но особо возражать не буду :_
   
конкретный язык не важен
важно , как мозги работают
алгоритм решения простой,  определяешь день недели первого числа следующего месяца и вычитаешь от этой даты (первого числа следующего месяца) соответствующее количество дней
для большинства языков, даже если ты первый раз на нем пишешь, реализация такого - это 15 минут гугления
 :-)o

Останнє редагування: 17 серпня 2018 19:46:10 від h2o
   

но, опять таки - it depends
во многих случаях выгодно сделать более простой алгоритм с лишней таблицей/джойном, чем заморачивать себя и будущего разработчика "хирым вывихом", в котором еще и разбираться надо будет


Саме це я і мав на увазі. Соррі, сам на ці граблі наступав неодноразово, коли моє супер-розумне і ніби "елегантне" рішення хтось старший не хотів сприймати. Робив нещодавно якусь сферічну геометрію, і мої колеги ніби то все нормально розуміли, але це ж треба ще перевіряти, і через рік-два-три, а їм жеж ліньки.
Про статистку і аналіз даних взагалі мовчу, вже боюсь щось казати. Повертаюсь до задачі за півтора роки і розумію, чому на ту роботу всі так ствердно і схвально кивали головую, але сильно розбиратися ніхто не поспішав.

Конкрето тут може і невелике ускладнення, але хоча б зробити окрему функцію обчислення дат, і її викликати вже тривіальним селектом.
   
конкретный язык не важен
важно , как мозги работают
алгоритм решения простой,  определяешь день недели первого числа следующего месяца и вычитаешь от этой даты (первого числа следующего месяца) соответствующее количество дней
для большинства языков, даже если ты первый раз на нем пишешь, реализация такого - это 15 минут гугления
 :-)o

без гугла, на клаптику паперу, в стресові ситуації , коли крім цієї ще декілька задач і обмежений час - доволі складно було ...

   
без гугла, на клаптику паперу, в стресові ситуації , коли крім цієї ще декілька задач і обмежений час - доволі складно було ...

Колись не зміг написати base64 encode / decode на папірці ... стидоба! (але трохи не здоровий був - треба було відмовитися від співбесіди ...)
   
select FROM_DAYS(
to_days(year(`DATA`))+
WEEK(date_format( date_add(`DATA`, INTERVAL 1 MONTH),'%Y-%m-01'))*7+5-1)
from tmptable;

Останнє редагування: 18 серпня 2018 00:49:21 від Воххобайт
   

Цю тему переглядають:

0 Користувачів і 1 гість
 
Повна версія