Pull to refresh
5
0
Send message

Вторая задача

select from_date, to_date, size from (
	-- определяем интервалы групп и максимальное количество параметров в группе
    select min(ts) from_date, max(coalesce(next_ts, 'infinity')) to_date, grp, size, max(size) over () max_size from (
		-- добавляем синтетическую id группы в виде кумулятивного кол-ва групп и добавляем дату начала следующей группы для определения конца данной группы
        select *, sum(case when coalesce(prev_size, 0) <> size then 1 else 0 end) over (order by ts) grp, lead(ts, 1) over (order by ts) next_ts from (
			-- делаем группы по adjacent датам с одинаковым кол-вом переопределенных параметров. сначала добавляем кол-во параметров из предыдущей группы, если это кол-во не равно текущему кол-ву параметру группы, то это новая группа
            select *, lag(size, 1) over (order by ts) prev_size from (
				-- добавляем количество переопределенных параметров на каждую дату. количество +1 если параметр не был переопределен и стал переопределен, -1 если был переопределен и стал не переопределен, иначе 0
                select *, sum(case when value is not null and prev_value is null then 1 when value is null and prev_value is not null then -1 else 0 end) over(order by ts) size
                from (                     
					-- добавляем предыдущее значение для каждого параметра на определенную дату
					select *, lag(value, 1) over(partition by parameter_name order by ts) prev_value
					from params
                ) t
            ) t
        ) t 
    ) t 	 
    group by grp, size
) t where size = max_size and size > 1
order by 1

Можно и гибче

with daily_jam as (
    select at, sum(qty) as qty
    from jam d     	 
    group by at
    having sum(qty) > 0
), fresh as (
	-- список дней, являющихся концом трехдневного марафона поедания варенья
    select d.at 
	from daily_jam d
    inner join daily_jam n on n.at > d.at - 3 and n.at < d.at -- два предыдущих дня
    group by d.at
    having (max(d.qty) + sum(n.qty)) > 3  -- количество банок за данный день и два предыдущих
	and count(n.at) = 2 -- два предыдущих дня имеют место быть
)
select count(*) from (
	select count(*) 
	from daily_jam d 
	inner join fresh f on f.at > d.at - 5 and f.at <= d.at -- данный день и четыре предыдущих венчали трехдневные поедания варенья
	group by d.at
	having count(*) = 5
) t

Это понятно. Но в задаче было 5 и 3 :) По факту это семь дней подряд с вареньем и еще так, чтобы любые три дня подряд из них было 4 и более банок варенья в сумме.

Господа, господа, вы упускаете одно решение (с) Рик и Морти

Задача про варенье, без оконных функций и т.д.

with daily_jam as (
  select at, sum(qty) as qty
  from jam
  group by at
  having sum(qty) > 0
)
select count(*)
from daily_jam d1
inner join daily_jam d2 on d2.at = d1.at - 1
inner join daily_jam d3 on d3.at = d1.at - 2 and (d1.qty + d2.qty + d3.qty) >= 4
inner join daily_jam d4 on d4.at = d1.at - 3 and (d2.qty + d3.qty + d4.qty) >= 4
inner join daily_jam d5 on d5.at = d1.at - 4 and (d3.qty + d4.qty + d5.qty) >= 4
inner join daily_jam d6 on d6.at = d1.at - 5 and (d4.qty + d5.qty + d6.qty) >= 4
inner join daily_jam d7 on d7.at = d1.at - 6 and (d5.qty + d6.qty + d7.qty) >= 4

Осталось еще вспомнить всякие убогие *=, =*, (+)

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

Не очень понял, что вы имели ввиду. Я про

t1

left outer join (

t2

inner join t3 on ...

) on ...

например

А ещё join-ы умеют объединяться вместе с помощью круглых скобочек.

У меня в 1995-ом был pentium 100, 16mb ram, 1gb hdd, sb 16, видеокарта s3 trio64, монитор 15 дюймов, тянул 1024х768. Стоило это в районе 1200 баксов. Когда пошли игры, поддерживающие ускорители, докупил 3dfx, процы менял 100->120->133->166, дальше не помню. Круто было, в общем.

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

И весь стандарт читать не надо, одну страницу от силы.

В стандарте все описано. Не считаю нужным перепечатывать его тут. Ссылка была дана выше.

Я говорю о том, помогают ли теоретические определения быстрее или правильнее писать SQL-запросы. Потому что это был ваш изначальный тезис. Нет, не помогают.

Ещё как помогают, и ваше определение джоинов и есть этот наглядный пример.

Короче, стандарт не читал и другим не советую. Определение join-ов не знаю, пишу по наитию, главное, что у меня в моей субд работает.

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

Вы не знаете, что SQL это декларативный язык. Я вам про то, что мы получаем, а вы про то, как мы это получаем.

А вы добавили две непонятные сущности "декартово произведение" и "фильтрация". Что дальше?

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

Фильтрация - ок, сделаем вид, что это непонятно. Тогда словами стандарта - подмножество декартова произведения двух таблиц, удовлетворяющее <join condition>.

Определение из стандарта самое простое и самое понятное. У него не может быть двух трактований или каких-то белых пятен. Ваше определение составлено вами для вас, используя вам понятный набор терминов. Лично для меня оно неочевидное и допускает разные трактования, что недопустимо. А все из-за того, что вы не желаете читать стандарты и изучать теоретические основы и побуждаете других поступать так же!

Если знает, как работает конструкция BLABLABLA JOIN в конкретной базе данных.

JOIN-ы работают везде одинаково, согласно стандарту. Если СУБД не соответствует стандарту, то фактически это не SQL, а какая-то его разновидность.

Очень просто. "Пишешь LEFT JOIN, и к каждой строке таблицы присоединяются все строки из другой таблицы, которые соответствуют условию. Так как в результате таблица, а не дерево объектов, то строка первой таблицы дублируется. INNER JOIN это то же самое, только строки из первой игнорируются, если нет строк во второй".

Вместо путанного определения, добавившего две непонятные сущности - "присоединяются" и "дублируются", в стандарте 92-ого года (взято для примера) inner join двух таблиц определяется как их декартово произведение с дальнейшей фильтрацией по условию. left join - это inner join union all строки из левой таблицы, не попавшие в результат inner join-а. Остальные join-ы выводятся аналогично и очень просто. См. 7.5 <joined table> в стандарте.

Стандарт SQL 1992: https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

Я искренне уверен, что для профессионального написания SQL запросов человек должен уметь читать стандарт и понимать, как это работает не на пальцах и непонятных определениях неизвестно откуда, а согласно первоисточнику.

Тот, кто забивает на основы, каждый раз будет удивляться тому, что разъезжаются данные при джоинах. База запросов - это джоины. Как можно понимать джоины без знания декартово произведения??

Если вы скажете, что вы эксперт SQL и не знаете, что такое декартово произведение, то вы либо обманываете окружающих, либо обманываете себя.

SQL невозможно выучить ни за неделю, ни за месяц, ни за год. Начинать надо с теоретических основ реляционных БД - кортежи, декартовы произведения, нормальные формы и тд, иначе запросы будут писаться наугад и работать на одних данных и выдавать лажу на других.

Я помню, когда ya.ru был только строкой поиска и кнопкой. По-моему, можно было на этом остановиться.

Пишут, что эту регистрацию практически невозможно пройти, по сути это белый список блоггеров.

Зачем байты в инт пихать? char (ну или что там ещё, uint8_t или что-то подобное) логичнее, меньше места жрет и & 0xFF не нужен.

А почему раз в секунду, а не раз в планковское время?

Information

Rating
Does not participate
Registered
Activity