PDA

View Full Version : یافتن رکوردهای جا افتاده



رضا عربلو
جمعه 30 شهریور 1386, 23:38 عصر
یک جدول داریم که در ان field1 از نوع Integer و pk است. در این جدول این فیلد بایستی مقادیرپشت سر همی بگیرد یعنی 1, 2, 3, ...
حال به هر دلیلی ممکن است بعضی شماره ها جا بمونند.
می خواستم این شماره های جا مونده را پیدا کنم (تا قبل از اخرین شماره). چه کوئری را پیشنهاد می کنید؟
یک روش به ذهن خودم رسید و اون هم ایجاد یک جدولtemporary و جوین ان با این جدول ولی خیلی ازش بدم اومد (به دلیل پرفورمنس پایین)

پویا
شنبه 31 شهریور 1386, 14:07 عصر
جدول را با خودش join کنین و شرطش رو اینجوری بذارین



select * from t1 left join t2
on t1.field1 = t2.field1 + 1
where t2.field1 is null

AminSobati
شنبه 31 شهریور 1386, 14:47 عصر
http://barnamenevis.org/forum/showthread.php?t=66951

MShirzadi
شنبه 31 شهریور 1386, 21:23 عصر
با این دستور هم میشه :
نام Table: dd
نام فیلدی که باید شماره بخوره:ID



select * From dd t1 where Not Exists(Select * From dd where id = t1.id+1)


من دستور آقای ÷ویا رو متوجه نشدم و به شکل زیر روی Table خودم هم تست کردم و جواب نگرفتم میشه یه کمی توضیح بدین چطوری آیا من اشتباه کردم یا نه ؟؟


select * from dd t1 left join dd t2
on t1.id = t2.id + 1
where t2.id is null


ازدوستانی هم که زحمت می کشن به ما یلری می رسونن بسیار متشکرم

پویا
یک شنبه 01 مهر 1386, 11:46 صبح
ایشون گفتن بعضی از اعداد پشت سر هم نیستند
دستوری که من نوشتم هر سطر رو با سطر بعدیش جوین میکنه
اگه بین دوتا عدد فاصله باشه اون عدد توی جدول دوم همتایی نداره

البته من این روشو چند سال پیش یه بار استفاده کردم
ممکنه الان درباره این مسئله درست جواب نده

MShirzadi
یک شنبه 01 مهر 1386, 12:15 عصر
ایشون گفتن بعضی از اعداد پشت سر هم نیستند
دستوری که من نوشتم هر سطر رو با سطر بعدیش جوین میکنه
اگه بین دوتا عدد فاصله باشه اون عدد توی جدول دوم همتایی ندارهدوست عزیز من یه چیزهایی از کارت متوجه شدم ولی فکر نکنم این راهش باشه و من هم داشتم تست میکردم



Select * from dd t1 left join dd t2
on t1.id = t2.id + 1
where t2.id is null
این تیبل رو با خودش join کردم (یعنی کاری که شما می خواستی بکنی)ولی جواب نداد
البته این روهم بگم فکر کنم بشه که با join کردن Table با خودش این کار رو انجام داد ولی من اون رو حفظ نیستم و Sql Server هم ندارم روش کار کنم اگه به این روش جواب گرفتی ما رو هم در جریان بذار
والبته دوستمون هم اعدادی رو که جا افتادن رو می خواست یعنی :
1,2,3,5,6,8,...
اگر Query روی یه همچین Table ی اجرا بشه باید 3 و 6 رو برگردونه چون 4 و 7 جا افتاده اند
با تشکر از تلاش تمام عزیزان

SYNDROME
یک شنبه 01 مهر 1386, 20:02 عصر
با سلام
می توانی از یک Table دیگر استفاده کنی و در آن اط عدد 1 تا عدد دلخواه را وارد کنید.
سپس با یک Select تو در تو عدد جا افتاده را به دست آورید.
موفق باشید

پویا
دوشنبه 02 مهر 1386, 12:30 عصر
سلام

من یه جدول ایجاد کردم و داخلش این اعداد رو ریختم
1،2،4،5،7،8
و این کوئری رو اجرا کردم


select * from #T
select t1.x + 1 from #T t1 left join #T t2
on t1.x = t2.x - 1
where t2.x is null


و نتیجه این شد
3،6،9
آخرین خط اشتباه است ولی بقیه را درست آورده
می تونین امتحان کنین
من از این روش برای قرار دادن خط های بدهکار و بستانکار سند ارسالی از زیر سیستم روبروی هم استفاده کرده بودم

رضا عربلو
دوشنبه 02 مهر 1386, 15:31 عصر
بلی کوئری را که دوستان نوشته اند تنها درصورتی می توان استفاده کرد که مطمئن بود تنها یا عدد جا مانده است و در موارد بیش از 1 عدد پشت سر هم جواب کامل را نمی دهد.
در اس کیو ال 2000 گویا چاره ای جز ایجاد temporary table وجود ندارد ولی در اس کیو ال 2005 همانطور که استاد الاستید در پست 3 لینک دادند روش بسیار موثرتر استفاده از Recursive وجود دارد که من برای تقریبا دو یست هزار رکورد اجرا کردم کمتر یک ثانیه طول کشید.

SYNDROME
دوشنبه 02 مهر 1386, 20:18 عصر
با سلام




select * from #T
select t1.x + 1 from #T t1 left join #T t2
on t1.x = t2.x - 1
where t2.x is null


می توانید اینجوری هم بنویسید.


select *
from Tbl_Rang
Where Code Not In
(Select Code
From Tbl_Teast
)

کلیه اعدادی که در Tbl_Test وجود ندارد را بر می گرداند و شما با یک Sort می توانید کوچکترین رکورد را برگردانید.
موفق باشید

Hamid.Kad
سه شنبه 03 مهر 1386, 10:05 صبح
شما میتونید از این روش استفاده کنید. با اینکه نعداد دستوراتش یه کم بیشتره ولی چون مرتبه خطی داره (نسبت به join که مرتبه نمایی داره) به مراتب سریعتر عمل میکنه. ضمن اینکه نیاز به ایجاد هیچ temp table ی هم نیست. این کد بزرگترین عددی که استفاده نشده را برمیگردونه.(با فرض اینکه اسم فیلد RegisterCode باشه)


declare @MaxGapId int, @Max int
set @MaxGapId = 0
select @Max = Max(Table1.REGISTERCODE)
from Table1

select @MaxGapId = case when isnull(@Max, 0) - 1 > T1.REGISTERCODE and @MaxGapId = 0 then isnull(@Max, 0) - 1
else @MaxGapId end
,Max = T1.REGISTERCODE@
from table1 as T1
where isnull(T1.REGISTERCODE, 0) > 0
order by T1.REGISTERCODE desc
print @MaxGapId

MShirzadi
سه شنبه 03 مهر 1386, 10:33 صبح
اولا جناب آقای Hamid.Kad لطف کنید کد های هودتون رو در قسمت کد قرار بدید تا خوانایی آنها بره بالا
ثانیا من یه سئوال دارم :
کدی رو که من در این تاپیک جواب دادم به این شکل بود

select * From dd t1 where Not Exists(Select * From dd where id = t1.id+1)



این کد یک خط هست و اگر اون رو به این شکل بنویسیم همون کاری رو که آقای رضا عربلو می خواستن انجام میشه حالا چرا باید این یه خط کد به چند خط کد مثل سایر کد های گفته شده تبدیل بشه


select top 1 Field1 From dd t1 where Not Exists(Select * From dd where id = t1.id+1)

میشه توضیح بدبد لطفا

Hamid.Kad
سه شنبه 03 مهر 1386, 10:49 صبح
جناب شیرزادی دلیلش رو توی پست قبلی هم عرض کردم


ولی چون مرتبه خطی داره (نسبت به join که مرتبه نمایی داره) به مراتب سریعتر عمل میکنه

اصولاً توی نوشتن کد مخصوصاً دستوراتی که با دیتابیس سروکار دارند،مهمترین هدف بالابردن راندمان و کم کردن زمان پاسخه و با زیاد شدن تعداد خطوط کد چنانچه راندمان بالا بره نه تنها چیزی رو از دست ندادیم که به هدف نهایی نزدیکتر شدیم.
اگه کد حقیر رو ملاحظه بفرمائید می بینید که مرتبه اجرایی اون در بدترین حالت o(n) هست ولی کد جنابعالی در بدترین حالت از مرتبه o(n^2) هست.
خود این امر مهمترین دلیل برای تغییر الگوریتم میتونه باشه.
امیدوارم قانع شده باشید

mrpn123
دوشنبه 20 اسفند 1386, 09:51 صبح
به این لینک یه سر بزن کارت راه میافته
http://barnamenevis.org/forum/showthread.php?t=97913