Size: a a a

SqlCom.ru - уголок MS SQL

2021 July 06

АР

Александр Ройтман... in SqlCom.ru - уголок MS SQL
Можно считать, что у каждой транзакции есть S-блокировка. Как минимум на БД.
Цель вашей хотелки совершенно не понятна.
источник

АР

Александр Ройтман... in SqlCom.ru - уголок MS SQL
Схематично:
select
*
from
(select 1, 2, 3) t1 (a, b, c) full join
(select 1, 2, 3) t2 (a, b, c) on 1 = 1;

select
*
from
(select 1, 2, 3 where 1 = 0) t1 (a, b, c) full join
(select 1, 2, 3) t2 (a, b, c) on 1 = 1;

select
*
from
(select 1, 2, 3) t1 (a, b, c) full join
(select 1, 2, 3 where 1 = 0) t2 (a, b, c) on 1 = 1;
источник

B

Bumos in SqlCom.ru - уголок MS SQL
Спасибо попробую
источник

Н

Николай in SqlCom.ru - уголок MS SQL
Ребят, привет) Посоветовали обратиться сюда за помощью.

Помогите, пожалуйста, оптимизировать запрос.

Есть таблица с данными
id   order_id                        mod_date
4    1000000000091298    2021-05-09 08:28:21.090
3    1000000000137327    2021-05-09 08:28:21.070
2    1000000000137327    2021-05-09 08:28:21.057
1    1000000000181967    2021-05-09 08:28:17.830

Нужно получить след. данные
id   order_id                        mod_date
4    1000000000091298    2021-05-09 08:28:21.090
3    1000000000137327    2021-05-09 08:28:21.070
1    1000000000181967    2021-05-09 08:28:17.830

Т.е. надо получить id, order_id и mod_date с максимальной датой изменения, до определённой даты, и не все сразу, а последовательно, т.к. данных там миллионы и желательно это распараллелить (я через python смогу это сделать).

Написал запрос, но он работает медленно (примерно 70 секунд на 1000 строк). Помогите, пожалуйста, оптимизировать запрос. БД MSSQL (какая версия точно не знаю)

Сам запрос
SELECT
DISTINCT order_id, mod_date, id
FROM
mytable as [data]
WHERE
mod_date < '2021-01-08 00:00:00'
AND
mod_date = (SELECT
           MAX(mod_date)
           FROM
           mytable
           WHERE
           order_id = [data].order_id)
ORDER BY mod_date
OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY

Также на mod_date ASC есть индекс формата Non-Clustered
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
Тут не на 1000 строк, а на строк, сколько лежит в таблице mytable, резалтсет может быть намного больше. Проблема здесь ещё в том, что не получится отсечь по дате, т.к. неизвестно есть ли для order_id в заданном диапазоне именно максимальное значение по mod_date.
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
По идее индекс по (order_id, mod_date DESC) возможно помог бы
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
Возможно такой вариант был бы лучше:
SELECT t.id,
 t.order_id,
 t.mod_date
FROM (
 SELECT id,
   order_id,
   mod_date,
   CASE WHEN ROW_NUMBER() OVER (
     PARTITION BY order_id
     ORDER BY mod_date DESC
   ) = 1 THEN 1 ELSE 0 END AS last_order_flag
 FROM mytable AS [data]
) AS t
WHERE t.last_order_flag = 1
 AND t.mod_date < '20210108'
OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY
источник

АР

Александр Ройтман... in SqlCom.ru - уголок MS SQL
with t as
(
select
 order_id, mod_date, id,
 row_number() over (partition by order_id order by mod_date desc) as rn
from
 mytable
where
 mod_date < '2021-01-08 00:00:00'
)
select
order_id, mod_date, id
from
t
where
rn = 1;
источник

Е

Енот in SqlCom.ru - уголок MS SQL
Здравствуйте, подскажите по синтаксису пож. Как в WHERE сделать выборку только по одному единственному слову, даже если есть то что нужно, но есть что то еще то как не учитывать такие столбцы?
источник

Н

Николай in SqlCom.ru - уголок MS SQL
Воу, спасибо, ребят. Пойду потестю)
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
Запрос может выдать результат, не такой, как в оригинальном, т.к. максимальный mod_date для некоторых order_id может быть больше, чем 2021-01-08
источник

Н

Николай in SqlCom.ru - уголок MS SQL
Если ставить
WHERE
mod_date < '2021-01-08 00:00:00'

то время выполнения увеличивается в 3 раза.
Похоже проще будет срезать лишнее с полученного, благо данных за полгода может быть всего около миллиона), а всего около 50 миллионов.
Сама таблица почти на млрд. записей.
источник

АР

Александр Ройтман... in SqlCom.ru - уголок MS SQL
B каким образом такое может получиться?
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
Александр например, для одного ордера есть 2 записи с mod_date = '2021-01-07 23:59:59' и mod_date = '2021-01-08 00:00:01'. Первоначальный запрос этот ордер не вернёт, а если отсекать дату сразу, то вернёт mod_date = '2021-01-07 23:59:59'
источник

Н

Николай in SqlCom.ru - уголок MS SQL
Да, все верно. Смысл был получить именно уже завершенные заказы (или заказы по которым ещё могу прийти сообщения, но точка синхронизации уже есть) до опр. даты. Поэтому и пришлось вкарячить mod_date < '2021-01-08 00:00:00' на уровне повыше.
источник

АР

Александр Ройтман... in SqlCom.ru - уголок MS SQL
where выполняется раньше ранжирующих функций. Поэтому описанное вами невозможно
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
Именно потому, что where выполняется раньше оно будет работать именно так, как я  написал
источник

Н

Николай in SqlCom.ru - уголок MS SQL
Сорри, если криво объяснил. Весь день сегодня мучался с этим запросом.
источник

АР

Александр Ройтман... in SqlCom.ru - уголок MS SQL
При таких данных первоначальный запрос вообще ничего не вернет. Что не соответствует озвученной задаче.
источник

AC

Alexey Chaykin in SqlCom.ru - уголок MS SQL
Ок, как скажешь.
источник