powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Счёт-Фактура
11 сообщений из 11, страница 1 из 1
Счёт-Фактура
    #40098036
LightN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость


Всем добрый день. Вот такая задача: есть один счёт (Invoice). По нему есть Приход и есть Расход.
ааа - пришло 10(2,1,2,3,2), ушло - 10(6,4)
bbb - пришло 10(1,3,2,4), ушло - 10(7,3)
ccc - пришло 10(4,1,5), ушло - 10(2,8)
Нужно получить Расход (Счёт-Фактуру, как результат Var1 или Var2) с атрибутами прихода (ГТД & Кол-во), так, чтобы ORDER BY в Приходе и Расходе был по дате, а кол-во выбиралось из Расхода сверху вниз.
Т.е. если нужно отдать товар ааа -12.01.21=4шт., то имеем ввиду то, что aaa - уже отдавалось ранее 6 шт. и берем (т.е. начинаем брать) с Прихода STU=3-1=2 и далее вниз по таблице Прихода пока кол-во не будет равно Расходу.
У меня эта задача решена процедурой + функцией с 2-мя курсорами, что сильно грузит БД. Данная задача каким-то способом решается в 1С, но к сожалению у меня клиентская часть не 1С. М.б. кто-то уже решал такую задачу или м.б. видит простой способ с хитрыми JOIN, так, чтобы это выглядело оптимально?
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098079
bideveloper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LightN,

картинок не видно
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098082
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
[img=http://c/Users/vovad/Desktop/SF.jpg]
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098090
LightN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
https://disk.yandex.ru/i/FsE-yzI4rRNPwA
Пробовал по разному, картинки не проходят #img=# , ни через [выберите файл] ... jpg, png, gif не лезут.
Gif пролез!!!
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098108
Oleg_SQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LightN,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
DECLARE @out TABLE(pn  VARCHAR(20), qty INT, dt  DATE);
DECLARE @in TABLE(pn   VARCHAR(20), dt   DATE, GTD  VARCHAR(20), qtyg INT);

insert @out values ('aaa', 6, '20210109'),('ccc', 2, '20210109'),('bbb', 7, '20210110'),
                   ('ccc', 8, '20210112'),('aaa', 4, '20210112'),('bbb', 3, '20210112')

insert @in values ('aaa', '20210101', 'ABC', 2),('aaa', '20210101', 'ABC2', 1),('bbb', '20210101', 'DEF', 1),
                  ('bbb', '20210101', 'DEF2', 3),('ccc', '20210101', 'JHI', 4),('aaa', '20210104', 'GKL', 2),
		  ('bbb', '20210104', 'MNO', 2),('ccc', '20210104', 'PQR', 1),('aaa', '20210107', 'STU', 3),
		  ('aaa', '20210107', 'STU2', 2),('bbb', '20210107', 'VWX', 4),('ccc', '20210107', 'YZA', 5)

;WITH nums
     AS (SELECT ROW_NUMBER() OVER(ORDER BY 1 / 0) AS n
           FROM STRING_SPLIT(REPLICATE(CAST(' ' AS VARCHAR(MAX)), 10000 - 1), ' ')),
     cte
     AS (SELECT ROW_NUMBER() OVER(PARTITION BY i.pn ORDER BY i.dt) AS rn, 
                i.pn AS pn2, i.dt AS dt2, i.GTD, x.qtyg
           FROM @in AS i
                OUTER APPLY (SELECT TOP (i.qtyg) 1 AS qtyg 
				      FROM nums
				    ORDER BY n) AS x),
     cte1
     AS (SELECT *
           FROM (SELECT *, 
                        _from = ISNULL(LAG(qty) OVER(PARTITION BY pn ORDER BY dt), 0) + 1, 
                        _to = SUM(qty) OVER(PARTITION BY pn ORDER BY dt)
                   FROM @out) AS o
          OUTER APPLY (SELECT * 
		                FROM cte AS i
		              WHERE i.pn2 = o.pn AND i.dt2 <= o.dt AND i.rn BETWEEN o._from AND o._to) AS i)
     SELECT pn, qty, dt, gtd, SUM(qtyg) AS qtyg
       FROM cte1
      GROUP BY pn, qty, dt, gtd
     ORDER BY dt, pn, gtd;



Я предварительно все строки "разбил" на число строк равное указанному кол-ву.
Например строка с кол-вом 6 заменяется 6-ю строками с кол-вом 1. Чтобы был корректный перенос по датам.
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098135
LightN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Oleg_SQL
LightN,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
DECLARE @out TABLE(pn  VARCHAR(20), qty INT, dt  DATE);
DECLARE @in TABLE(pn   VARCHAR(20), dt   DATE, GTD  VARCHAR(20), qtyg INT);

insert @out values ('aaa', 6, '20210109'),('ccc', 2, '20210109'),('bbb', 7, '20210110'),
                   ('ccc', 8, '20210112'),('aaa', 4, '20210112'),('bbb', 3, '20210112')

insert @in values ('aaa', '20210101', 'ABC', 2),('aaa', '20210101', 'ABC2', 1),('bbb', '20210101', 'DEF', 1),
                  ('bbb', '20210101', 'DEF2', 3),('ccc', '20210101', 'JHI', 4),('aaa', '20210104', 'GKL', 2),
		  ('bbb', '20210104', 'MNO', 2),('ccc', '20210104', 'PQR', 1),('aaa', '20210107', 'STU', 3),
		  ('aaa', '20210107', 'STU2', 2),('bbb', '20210107', 'VWX', 4),('ccc', '20210107', 'YZA', 5)

;WITH nums
     AS (SELECT ROW_NUMBER() OVER(ORDER BY 1 / 0) AS n
           FROM STRING_SPLIT(REPLICATE(CAST(' ' AS VARCHAR(MAX)), 10000 - 1), ' ')),
     cte
     AS (SELECT ROW_NUMBER() OVER(PARTITION BY i.pn ORDER BY i.dt) AS rn, 
                i.pn AS pn2, i.dt AS dt2, i.GTD, x.qtyg
           FROM @in AS i
                OUTER APPLY (SELECT TOP (i.qtyg) 1 AS qtyg 
				      FROM nums
				    ORDER BY n) AS x),
     cte1
     AS (SELECT *
           FROM (SELECT *, 
                        _from = ISNULL(LAG(qty) OVER(PARTITION BY pn ORDER BY dt), 0) + 1, 
                        _to = SUM(qty) OVER(PARTITION BY pn ORDER BY dt)
                   FROM @out) AS o
          OUTER APPLY (SELECT * 
		                FROM cte AS i
		              WHERE i.pn2 = o.pn AND i.dt2 <= o.dt AND i.rn BETWEEN o._from AND o._to) AS i)
     SELECT pn, qty, dt, gtd, SUM(qtyg) AS qtyg
       FROM cte1
      GROUP BY pn, qty, dt, gtd
     ORDER BY dt, pn, gtd;



Я предварительно все строки "разбил" на число строк равное указанному кол-ву.
Например строка с кол-вом 6 заменяется 6-ю строками с кол-вом 1. Чтобы был корректный перенос по датам.

Спасибо!
Проверю на скорость...
Я тоже использую STRING_SPLIT.
От него видно никуда не деться ...
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098143
Oleg_SQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LightN,


Поправил немного, если данных больше, то _From нужно считать тоже накопительно:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
;WITH nums
     AS (SELECT ROW_NUMBER() OVER(ORDER BY 1 / 0) AS n
           FROM STRING_SPLIT(REPLICATE(CAST(' ' AS VARCHAR(MAX)), 10000 - 1), ' ')),
     cte
     AS (SELECT ROW_NUMBER() OVER(PARTITION BY i.pn ORDER BY i.dt, gtd) AS rn, 
                i.pn AS pn2, i.dt AS dt2, i.GTD, x.qtyg
           FROM @in AS i
                OUTER APPLY (SELECT TOP (i.qtyg) 1 AS qtyg 
                      FROM nums
                    ORDER BY n) AS x),
     cte1
     AS (SELECT *
           FROM ( SELECT *, _from = ISNULL(LAG(_to) OVER(PARTITION BY pn ORDER BY dt), 0) + 1 
                   FROM (SELECT *, _to = SUM(qty) OVER(PARTITION BY pn ORDER BY dt)
                          FROM @out) z) AS o
          OUTER APPLY (SELECT * 
                        FROM cte AS i
                      WHERE i.pn2 = o.pn AND i.dt2 <= o.dt AND i.rn BETWEEN o._from AND o._to) AS i)
     SELECT pn, qty, dt, gtd, SUM(qtyg) AS qtyg
       FROM cte1
      GROUP BY pn, qty, dt, gtd
     ORDER BY dt, pn, gtd;



Ну собственно, по мере использования могут возникать доработки, но направление есть )))
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098152
Oleg_SQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LightN

Я тоже использую STRING_SPLIT.
От него видно никуда не деться ...


Много раз писали уже - создайте таблицу с нужным кол-вом строк (миллион, льярд или тп) и используйте ее всегда - серверу будет приятно )))
Я в примере привел nums за неимением ссылки на таковую
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098438
LightN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Oleg_SQL,
Спасибо, Спасибо. Ваше решение немного отличается от моего. Как я уже писал я тоже использовал split.
Мне казалось, что м.б. найдется какое-то иное решение без него. Какой-нибудь SQL-Перельман ткнет носом - ну вот же решение.
Ведь существует огромная потребность на join с такой структурой. И только 1С не напрягается этой проблемой.
Сотни тысяч компаний что-то перепродают, и конечно там есть qty прихода и qty расхода. И я вижу насколько востребовано JOIN на это решение. Видно как некоторые компании выпускают расходные документы, где таблицы идут по 1 штуке. Либо не додумались до split, либо там его нет, либо он стопорит систему своей работой, либо просто некуда деться. И там где можно обойтись 1 листом бумаги, приходит 10 страниц. Подождём MS, м.б. когда-то сделают ...
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098473
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LightN
Как я уже писал я тоже использовал split.
Мне казалось, что м.б. найдется какое-то иное решение без него. Какой-нибудь SQL-Перельман ткнет носом - ну вот же решение.
Ну вот же решение:
Oleg_SQL
Много раз писали уже - создайте таблицу с нужным кол-вом строк (миллион, льярд или тп) и используйте ее всегда - серверу будет приятно )))
...
Рейтинг: 0 / 0
Счёт-Фактура
    #40098676
LightN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexeyvg ,
Вы меня неправильно поняли.
Таблицу с "льярд" конечно же создал, а вот печалька совсем в другом была.
Приход -Join(New)-Расход, и всё. И нет никаких ROW_NUMBER(), LAG() и OVER(PARTITION BY).
Ведь так работает любая складская или какая-нибудь другая распределительная система и запрос на такой именно системный join думаю очень был бы востребован ...

Oleg_SQL , ещё раз СПАСИБО. Внедрил, работает, быстрее ...
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Счёт-Фактура
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]