Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Svetaahm Member Откуда: Сообщений: 7 |
******************************* Люди добрые помогите решить проблему, без рекурсии пробовал вообще не работает... Необходимо ускорить процесс выбора свободного номера. Номера формируются по следующему алгоритму: 1. Очистить таблицу резервных номеров за прошлые сутки 2. Выбрать первый свободный номер в году (не следующий после максимального, а именно первый свободный, если считать начиная с единицы). При этом занятые резервные номера также брать нельзя. 3. Зарезервировать номер в таблице XAF.CD_Bookings_Doc_Number Сообщение было отредактировано: 3 июл 19, 18:44 |
|
3 июл 19, 18:08 [21920154] Ответить | Цитировать Сообщить модератору |
aleks222 Member [заблокирован] Откуда: Сообщений: 1240 |
Эпический бред. Сгенерите вы все свои номерки в постоянную таблицу и выбирайте. |
3 июл 19, 18:23 [21920171] Ответить | Цитировать Сообщить модератору |
PizzaPizza Member Откуда: Сообщений: 416 |
Есть несколько вариантов нахождения пропущенных значений. Рекурсия уж точно тут не нужна как и
-- максимальный из используеммых и забронированных номеров
Например вы можете использовать min()+1 NOT EXISTS ... +1 к вашей выборке, где вы ищите первое пропущенное значение. WITH u AS ( SELECT * FROM ( VALUES (1) , (2) , (8) , (9) , (21) , (22) , (23) , (1025) ) AS b(nomer) ) SELECT min(u.nomer) + 1 FROM u WHERE NOT EXISTS ( SELECT * FROM u AS u2 WHERE u2.nomer = u.nomer + 1 ) |
4 июл 19, 03:05 [21920396] Ответить | Цитировать Сообщить модератору |
Yuri Abele Member Откуда: Латвия> Литва > Тольятти > Wiesbaden > Karlsruhe Сообщений: 1661 |
Я для подобного такой TABLE VALUE UDF пользуюсь:CREATE FUNCTION dbo.GenerateRows (@Count INT) /* https://yabele.blogspot.com/2017/07/mssql-function-to-generate-empty-rows.html */ RETURNS TABLE AS RETURN WITH TenRows AS ( SELECT * FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS T(I) ) SELECT TOP(@Count) I = ROW_NUMBER() OVER(ORDER BY (SELECT 1)) FROM TenRows T1 CROSS JOIN TenRows T2 CROSS JOIN TenRows T3 CROSS JOIN TenRows T4 CROSS JOIN TenRows T5 /* SELECT * FROM dbo.GenerateRows(100); */ ; А с ней уже EXCLUDE пересечение и забирать MIN значение. Если 10000 значений мало, добавьте еще сколько надо CROSS JOINов. |
4 июл 19, 12:09 [21920635] Ответить | Цитировать Сообщить модератору |
Сруль. Member Откуда: Сообщений: 121 |
Я не стал разбираться с вашими расчётами. Если по-большому: таблицу занятых номеров вы как-то строите? Ведь так? Постройте вспомогательную таблицу с полем пробелом и айдентити-инт. Загоните туда 200,000 записей. При желании-это один инсерт-селект . Сделайте во вспомог. таблице делит, глядя в таблицу занятых номеров. Первая запись, что осталась-ваша. |
4 июл 19, 15:23 [21920844] Ответить | Цитировать Сообщить модератору |
Svetaahm Member Откуда: Сообщений: 7 |
Yuri Abele, Спасибо, вы мне очень помогли! |
6 июл 19, 17:09 [21922051] Ответить | Цитировать Сообщить модератору |
Svetaahm Member Откуда: Сообщений: 7 |
Люди! решила свою проблему вот таким образом:
Только проблема в том, что в таблицу XAF.CD_Bookings_Doc_Number записывается один и тот же номер, а нужно чтоб следующий из не занятых номеров. Что нужно и куда дописать, чтоб сравнирь @DocNumbers и XAF.CD_Bookings_Doc_Number, если в XAF.CD_Bookings_Doc_Number есть минимальный номер, то записать в таблицу следующий из @DocNumbers Сообщение было отредактировано: 7 июл 19, 19:08 |
|
7 июл 19, 15:10 [21922243] Ответить | Цитировать Сообщить модератору |
aleks222 Member [заблокирован] Откуда: Сообщений: 1240 |
Зачем весь этот бред?USE [Om*] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [XXX].[DD_GeXXXXXXX] AS BEGIN SET NOCOUNT; declare @now date = GETDATE(); -- ======================================================================================================================= -- очистка бронированных номеров старше 1 дня -- ======================================================================================================================= DELETE XAF.CD_Bookings_Doc_Number WHERE D_Date < DATEADD(day, -1, @now ); -- ======================================================================================================================= declare @yearStart date = dateadd( day, 1 - day(@now), dateadd( month, 1 - month(@now), @now ) ); declare @UsedNumbers table( C_number int primary key ); with rn as ( SELECT dd.C_NUMBER , CASE WHEN (ISNUMERIC(dd.C_Number) = 1 AND dd.C_Number NOT LIKE '%[.,]%') THEN CAST(dd.C_Number AS INT) END C_number2 -- только коректные номера FROM dbo.DD_Docs as dd INNER JOIN dbo.DS_Docum_Types as ddt ON ddt.LINK = dd.F_Docum_Types where ddt.C_Const IN ('DST_ToleranceFirst', 'DST_ToleranceNext', 'DST_Checkup', 'DST_Return', 'DST_Survey', 'DST_Survey_TES', 'DST_Checkup_TES', 'DST_Return_TES', 'DST_ControlCheckup','DST_AnnulateAct','DST_TU_Giving', 'DST_UU_Matching') and @yearStart <= dd.D_Register_Date and dd.D_Register_Date < dateadd( year, 1, @yearStart ) and dd.C_number not in ('a','БДИ') ) insert @UsedNumbers select C_number2 from rn; insert XAF.CD_Bookings_Doc_Number SELECT min(C_Number) + 1, GETDATE() from @UsedNumbers as t1 where not exists( select * from @UsedNumbers as t2 where t2.C_number = t1.C_number + 1 ) and not exists( select * from XAF.CD_Bookings_Doc_Number as t2 where t2.C_number = t1.C_number + 1 ) ; SELECT C_Number from XAF.CD_Bookings_Doc_Number; END |
7 июл 19, 16:12 [21922252] Ответить | Цитировать Сообщить модератору |
aleks222 Member [заблокирован] Откуда: Сообщений: 1240 |
Впрочем, так будет православнееALTER PROCEDURE [XXX].[DD_GeXXXXXXX] AS BEGIN SET NOCOUNT; declare @now date = GETDATE(); -- ======================================================================================================================= -- очистка бронированных номеров старше 1 дня -- ======================================================================================================================= DELETE XAF.CD_Bookings_Doc_Number WHERE D_Date < DATEADD(day, -1, @now ); -- ======================================================================================================================= declare @yearStart date = dateadd( month, 1 - month(@now), dateadd( day, 1 - day(@now), @now ) ); declare @UsedNumbers table( C_number int primary key ); begin transaction with rn as ( SELECT dd.C_NUMBER , CASE WHEN (ISNUMERIC(dd.C_Number) = 1 AND dd.C_Number NOT LIKE '%[.,]%') THEN CAST(dd.C_Number AS INT) END C_number2 -- только коректные номера FROM dbo.DD_Docs as dd INNER JOIN dbo.DS_Docum_Types as ddt ON ddt.LINK = dd.F_Docum_Types where ddt.C_Const IN ('DST_ToleranceFirst', 'DST_ToleranceNext', 'DST_Checkup', 'DST_Return', 'DST_Survey', 'DST_Survey_TES', 'DST_Checkup_TES', 'DST_Return_TES', 'DST_ControlCheckup','DST_AnnulateAct','DST_TU_Giving', 'DST_UU_Matching') and @yearStart <= dd.D_Register_Date and dd.D_Register_Date < dateadd( year, 1, @yearStart ) and dd.C_number not in ('a','БДИ') ) insert @UsedNumbers select C_number2 from rn union all select C_number2 from XAF.CD_Bookings_Doc_Number ; insert XAF.CD_Bookings_Doc_Number SELECT min(C_Number) + 1, GETDATE() from @UsedNumbers as t1 where not exists( select * from @UsedNumbers as t2 where t2.C_number = t1.C_number + 1 ) ; commit transaction; SELECT C_Number from XAF.CD_Bookings_Doc_Number; END |
7 июл 19, 16:16 [21922255] Ответить | Цитировать Сообщить модератору |
Svetaahm Member Откуда: Сообщений: 7 |
Увы нет! min(C_Number) + 1 -- выбирает как в математике +1. например: первый свободный номер в базе 3275, первый раз программа его выбирает и записывает в таблицу, второй раз программа выбирает 3276, но этот номер занят.... |
7 июл 19, 16:46 [21922265] Ответить | Цитировать Сообщить модератору |
Svetaahm Member Откуда: Сообщений: 7 |
По аналогии я так пробовала, чуть по другому у меня код выглядел... |
7 июл 19, 16:47 [21922266] Ответить | Цитировать Сообщить модератору |
Svetaahm Member Откуда: Сообщений: 7 |
aleks222,Спасибо за помощь, но ваш запрос не работает, как бы я его не видоизменяла. Пишет! (0 row(s) affected) Msg 2627, Level 14, State 2, Line 36 Violation of PRIMARY KEY constraint 'PK__#ABAE134__2F653DEB25F6E8D6'. Cannot insert duplicate key in object 'dbo.@UsedNumbers'. The duplicate key value is (92). |
7 июл 19, 17:04 [21922269] Ответить | Цитировать Сообщить модератору |
aleks222 Member [заблокирован] Откуда: Сообщений: 1240 |
insert @UsedNumbers select C_number2 from rn union select C_number2 from XAF.CD_Bookings_Doc_Number ; только это как-то неаккуратненько. ЗЫ. Желательно понять, а не повторить. |
7 июл 19, 17:17 [21922271] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9644 |
ЗЫ: Если данная процедура вызывается одновременно в нескольких сессиях - рискуете бронировать один и тот же номер несколько раз. |
||
7 июл 19, 17:25 [21922273] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |