SQL Server
3.94K subscribers
19 photos
7 videos
36 files
168 links
حمید رضا صادقیان

🔴طراح‌ومشاوربانک های اطلاعاتیSQLSERVER
⚫️مدرس دوره های آموزشیDatabase

ارتباط با من:
@Hamidreza_Sadeghian

گروه تبادل نظر:
https://t.me/+uIc1qhv58gU0NWQ0
Download Telegram
سلام و عرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوش باشه
یکی از مواردی که اخیرا خیلی با من تماس میگیرند، د ر خصوص پیدا کردن شخص و Ip و مشخصات سیستمی هست که مثلا اومده داده هارو دستکاری کرده و یک سری جداول و داده ها حذف شدند یا تغییر پیدا کردن.!!!
قبل از هرچیز خیالتون رو راحت کنم که به صورت پیشفرض SQL Server این موارد رو Log نمیگیره و جایی ثبت نمیکنه ( به جز یک مورد که عرض می کنم).
اول اینکه چند تا سوال پیش میاد.

۱- چرا اصلا باید این اتفاق بیافته؟؟؟؟ مگه سازمانها DBA ندارند؟ ( شخصی که مسئول شبکه است و فقط بلده SSMS رو باز کنه و در نهایت یک Shrink کنه یا Backup بگیره یا یک Login تعریف کنه و یا یک Session رو با استفاده از Activity monitor پیدا کنه و kill ! کنه ، DBA نخواهد بود )

۲- چرا باید Login sa شما دست هر کسی باشه؟ چرا هر شخصی به راحتی باید بتونه به سرور عملیاتی یک سازمان دسترسی پیدا کنه؟
بارها مشاهده کردم که شرکتهای نرم افزاری درخواست دسترسی کامل به سرور رو کردند و نیاز به لاگین SA داشتند ( باعرض معذرت از تمامی عزیزان شرکتهای نرم افزاری) باید عرض کنم که به هیچ وجه ،به هیچ وجه ، به هیچ وجه اصلا شرکتهای نرم افزاری نباید دسترسی به سرور داشته باشند . وقتی نرم افزار نصب شد ، مالک داده و دیتابیس سازمان هست نه شرکتها . متاسفانه شرکتهای نرم افزاری این رو به اشتباه متوجه شدند در صورتی که اصلا تحت هیچ شرایطی نباید دسترسی داشته باشند.
اگر قرار هست تغییراتی روی دیتابیس صورت بگیره بدون استثنا باید در حضور ادمین سازمان باشه و لاغیر.

۳- چطوره که یک سازمان ، نمیدونه چطوری باید موارد مختلف نظارتی رو بر روی سرور دیتابیس ها که حساس ترین جز یک سازمان هست ، پیاده سازی کنه؟

خوب حالا برسیم به نوع Log ها. ببینید اگر دیتابیس شما Recovery Model اون روی Full باشه فقط میتونید ببینید چه شخصی در چه زمانی چه دیتایی رو تغییر داده همین! هیچ IP به شما نخواهد داد .
در Trace های پیش فرض خود SQL Server نیز این موارد لاگ نمی شوند. پس باید توسط DBA !( بله یکی از وظایف DBA این هست) این موارد راه اندازی و تنظیم بشه و مرتب مانیتور بشه.
مورد بعدی این هست که معمولا چون اکثر نرم افزارها با یک لاگین SQL یا windows به دیتابیس وصل میشن ، پس عملا همه تغییرات موجود در فایل LDF نیز به نام همین لاگین ثبت خواهد شد.!
پس بهتره نرم افزارها راه حلی برای این مورد نیز داشته باشند.
امیدوارم سازمانها ، شرکتها و موسساتی که داده های آنها براشون اهمیت داره ، به این بلوغ فکری برسند که وظیفه مدیر IT ، مسئول شبکه ، برنامه نویس ، مدیر تیم نرم افزار ، نگهداری از دیتابیس نیست. و اگر این افراد مهارتهای لازم در این حوزه رو نداشته باشند به آنها DBA گفته نمی شود.
DBA شخصی است که باید در تمام زمینه های زیر مهارت کافی داشته باشه.
۱- مسلط به ساختار درونی SQL Server
2- مسلط به زبان T-SQL
۳- مسلط به مباحث Administration
۴- مسلط به مباحث Performance Tuning
۵- آشنایی کافی نسبت به سخت افزار سرور
۶- آشنایی با مباحث امنیتی و سطوح دسترسی در SQL Server
۷- شناخت کافی نسبت به سایر سرویس های SQL Server نظیر SSAS،SSRS,MDM,DQS,SSIS

اگر افرادی که درحال مدیریت دیتابیس های شما هستند دارای این مهارتها هستند که عالیه. درغیر اینصورت پیشنهاد میکنم تا یک مشکلی برای دیتابیس هاتون رخ نداده، یک شخصی که این توانایی هارو داشته باشه انتخاب کنید و در این پست قرار بدین.

ارادتمند شما
حمیدرضا صادقیان
ID : @Hamidreza_Sadeghian
سلاو عرض ادب خدمت دوستان عزیزم
امیدوارم حالتون خوب باشه.
در این پست پوستر Logical Query Processing رو قرار میدم که توسط حضرت Itzik Ben-Gan (دامت برکاته 😅) تهیه شده.
اینکه شما بدونید SQL Server چطوری دستوراتش رو اجرا می کنه و با کدهای شما رفتار می کنه ، باعث میشه که کدهای بسیار باکیفیت تری رو بنویسید.
این پوستر رو دقیق مطالعه کنید و اگر سوالی یا ابهامی بود میتونید از من بپرسید ، درحد توانم کمکتون خواهم کرد.

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
سلام و عرض ادب خدمت دوستان گرامی
شاید برای شما هم پیش اومده باشه که کدی رو در نرم افزار اجرا می کنید خیلی کنده ولی وقتی همون کد رو در SSMS اجرا می کنید خیلی سریع اجرا میشه.
یکی از دلایل این امر میتونه Parameter Sniffing باشه که باعث میشه پلن ایجاد شده در نرم افزار با چیزی که در SSMS تولید میشه تفاوت داشته باشه.
یکی از مسائلی که میتونه سبب این مشکل بشه و دیباگ رو سخت بکنه گزینه ArithAbort هست.
کار این گزینه این هست که در کدهایی که باعث Overflow, Divison by zero میشن اگر on باشه خطا میده و اگر off باشه و در حال Insert,Update باشید و اون ستونها اجازه درج Null رو بده ، علامت Null رو درج میکنه( Null یک مقدار نیست اشتباه نگیرید.!! یک علامت یا Marker هست. Null برابر Unknown هست یعنی نمیدونیم چه مقداری هست به همین خاطر از این علامت استفاده می کنیم)
خوب حالا چرا این سوییچ میتونه مشکلساز بشه. دلیلش این هست که در نرم افزارها به صورت پیش فرض این گزینه Off هست و در SSMS به صورت پیش فرض ON هست.( که بهتره همیشه On باشه) وقتی شما کدی رو از سمت نرم افزار اجرا می کنید و اگر قبلا این کد اجرا شده باشه و پلنی براش ایجاد شده باشه از اون پلن استفاده می کنه. در SSMS چون شما دارید با سوییچ ON دستورتون رو اجرا می کنید و چون با این سوییچ پلنی برای کد شما ساخته نشده ، پس یک پلن جدید بر اساس مقادیر و پارامترهای جدید براتون ساخته میشه و به همین دلیل سبب میشه که خیلی سریع اجرا بشه.
زمانی که دارید دیباگ انجام میدین بهتره تنظیمات سمت نرم افزار و SSMS مشابه هم باشن که دچار مشکل نشید.

دقت کنید که این گزینه برای حل مساله Parameter Sniffing نیست و باید دنبال این مساله گشته و ایراد رو مرتفع کنید.

ارادتمند شما
حمیدرضا صادقیان

ID :@Hamidreza_Sadeghian
سلام و عرض ادب خدمت دوستان عزیزم
امیدوارم حالتون خوب و خوش باشه
تصمیم دارم در سلسله مباحثی ، دستور زبان T-SQL رو بیشتر توضیح بدم و شمارو با نکاتی آشنا کنم که شاید کمتر باهاش برخورد کرده باشین.
در این جلسه میخوام از ترکیب Set Operations و Join ها با شما صحبت کنم.
فرض کنید ما تصمیم داریم بین دو تا جدول Inner join بزنیم ولی یکی از فیلدهای شرط ما Null هست.
خوب اگر ما بیایم این دو فیلد رو مساوی قرار بدیم ، چون Null نمیتونه مساوی قرار بگیره پس در واقع در شرط به صورت Unknown ارزیابی میشه و مقدار False برمیگردونه ولی براساس شرط ما این ردیف نیز باید برگرده.
راه دوم این هست که بیایم این دوفیلد رو با مقدار Isnull باهم مقایسه کنیم.
SELECT EL.country, EL.region, EL.city, EL.numemps, CL.numcusts
FROM dbo.EmpLocations AS EL
INNER JOIN dbo.CustLocations AS CL
ON EL.country = CL.country
AND ISNULL(EL.region, N'<N/A>') = ISNULL(CL.region, N'<N/A>')
AND EL.city = CL.city;
در اینجا مشکل ما حل میشه و مقدار رکورد مورد نظر برمیگرده ولی چون فیلدهای Region دستخوش تغییرات شدن در جستجوهای ما SQL Server دیگه به Sort بر روی این فیلدها نگاهی نمیکنه ( اگر ایندکسی بر روی انها باشه و سورت شده باشه )‌و اگر رکوردها زیاد باشن و Merge join انجام بشه خودش یک Sort انجام میده. یا در تعداد پایین میاد ابتدا Index Seek بر روی شرط Country انجام میشه و دو شرط بعدی در واقع بر روی کل رکوردهای باقی مانده انجام میشه.که یک مقایسه زیادی هست.
راه سوم این هست که بیایم ازدستور Isnull استفاده کنیم.
SELECT EL.country, EL.region, EL.city, EL.numemps, CL.numcusts
FROM dbo.EmpLocations AS EL
INNER JOIN dbo.CustLocations AS CL
ON EL.country = CL.country
AND (EL.region = CL.region OR (EL.region IS NULL AND CL.region IS NULL))
AND EL.city = CL.city;
در این روش کل شرط ها در Index Seek انجام میشه و پلن بهینه ای خواهیم داشت و از Sort روی ایندکسها نیز بهره میبره.

راه بعدی هم ترکیب Set Operation ها و Join هستش.
SELECT EL.country, EL.region, EL.city, EL.numemps, CL.numcusts
FROM dbo.EmpLocations AS EL
INNER JOIN dbo.CustLocations AS CL
ON EXISTS (SELECT EL.country, EL.region, EL.city
intersect
SELECT CL.country, CL.region, CL.city);
در این روش پلن ایجاد شده مانند کد قبل هست و پلن بهینه ای تولید میشه. و چون Intersect میتونه Null رو ارزیابی کنه پس اون ردیفی که دارای Region برابر Null هست نیز داخل رکوردهای ما هست و در پلن بیرونی نیز ارزیابی میشه.

امیدوارم این نکته به دردتون خورده باشه.
سوالاتتون رو میتونید در خصوصی مطرح کنید

ارادتمند شما
حمیدرضا صادقیان
ID: @Hamidreza_Sadeghian
Channel : @SQL_Server
TSQLV4.rar
47.9 KB
این اسکریپت ساخت دیتابیس مورد نظر هست
DROP TABLE IF EXISTS dbo.EmpLocations;
SELECT country, region, city, COUNT(*) AS numemps
INTO dbo.EmpLocations
FROM HR.Employees
GROUP BY country, region, city;
ALTER TABLE dbo.EmpLocations ADD CONSTRAINT UNQ_EmpLocations
UNIQUE CLUSTERED(country, region, city);


DROP TABLE IF EXISTS dbo.CustLocations;
SELECT country, region, city, COUNT(*) AS numcusts
INTO dbo.CustLocations
FROM Sales.Customers
GROUP BY country, region, city;
ALTER TABLE dbo.CustLocations ADD CONSTRAINT UNQ_CustLocations
UNIQUE CLUSTERED(country, region, city);


این دوهم اسکریپت ساخت جداول مورد نیاز برای اجرای کد بالا هست
سلام و عرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوب باشه
در اکثر جاهایی که مشاوره دادم ، بارها مشاهده کردم که نیاز بوده یک رشته ای که با , از هم جدا شده نیاز بوده به صورت جدول تبدیل بشه و برای این امر شروع به نوشتن توابعی کردن که معمولا بهینه نبوده.
از نسخه ۲۰۱۶ به بعد تابعی به اسم String_split به زبان قدرتمند T-SQL اضافه شده که اینکارو برای شما می کنه.
برای استفاده ا زاین تابع حتما باید Compatibility level برابر ۱۳۰ یا بزرگتر باشه.
نمونه استفاده این تابع هم در کد زیر ملاحظه می کنید.

DECLARE @orderids AS VARCHAR(MAX) = N'10248,10542,10731,10765,10812';
SELECT value
FROM STRING_SPLIT(@orderids, ',');

به دلیل این که یک Result Set برگردانده میشه میتونید درر Join ها و Apply و ... نیز استفاده کنید.

ارادتمند شما
حمیدرضا صادقیان
ID : @Hamidreza_Sadeghian
Channel : @SQL_Server

#T-SQL_Hints
#String_Split
سلام و عرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوش باشه
یک اتفاق جالب افتاد خواستم باهاتون به اشتراک بذارم تا به وضعیت مدیریت دیتابیس های دانشگاهها پی ببرید.
برای یکی از دوستان داشتم برای دانشگاه الکترونیکی آزاد ثبت نام انجام می دادم ، به محض اینکه خواستم به قسمت ثبت نام وارد بشم بهم پیغام داد که Transaction Log پر شده و شما نمی تونید کاری بکنید.😁😁😁
دانشگاهی که داعیه تحصیل مجازی رو داره و باید حداقل در خدمات مجازی ساختار مناسبی رو داشته باشه ، با این وضعیت روبرو شده.
احتمالا الان به مسئول شبکه یا کسی که اونجا یک ذره بلده با ویندوز کار کننه 😂😂 می گن که برو توی SSMS و دیتابیس رو ببر توی حالت Simple و بعد هم Shrink کن. اون بنده خدا هم میبینه که مشکل حل شده احتمالا کلی کیف می کنه که مشکل سایت دانشگاه آزاد رو حل کرده.
خیلی عجیبه که حتی یک جاب ساده برای تهیه Log Backup نذاشتن که این اتفاق خیلی پیش پا افتاده رخ نده. یعنی حتی احتمال این هم ندادن که موقع ثبت نام ها احتمالا تعداد تراکنش ها زیاد میشه و با مشکل مواجه خواهند شد.
تصویر این خطا رو در پست بعد براتون ارسال می کنم

شاد باشید
ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
سلام و عرض ادب خدمت دوستان گرامی
شب بر همگان خوش باشه
یکی از مواردی که در اکثر مشاوره ها در شرکتها باهاش برخورد کردم نحوه نوشتن کدها در زبان شیرین T-SQL بوده .
دوستانی که دارن کد T-SQL می نویسند باید به این نکته توجه کنند که زبان T-SQL یک زبان توصیفی یا Declarative هست.
زبانهای برنامه نویسی مثل C# یا Delphi اینها Procedural هستند.
شما نباید با همون منطقی که در زبانی مثل سی شارپ تفکر می کنید و کد می نویسید ،در زبان T-SQL هم کد بنویسید.
بارها دیدم که مشکلات خیلی راحت حل می شدن ولی چون تفکر Procedural بوده یا حلقه while در کدها تعریف شده یا از جداول Temp به شدت استفاده شده یا Cursor تعریف شده که گاها با یک Select یا update یا Insert به راحتی حل شده و Performance اون چند ده برابر نیز شده است.
زبان T-SQL از زبان SQL مشتق شده که یک زبان با استاندارد Ansi هست. این زبان از Relational Model اقتباس شده که خود Relational Model از ترکیب Set Theory و Predicate Logic ایجاد شده است.
پس وقتی که شما دارید کدنویسی می کنید باید به صورت Set Based به داده ها نگاه کنید نه یک رکورد از یک جدول.
شما نباید هیچ وقت هیچ وقت هیچ وقت در کد نویسی T-SQL برای SQL Server الگوریتم مشخص کنید. وقتی که در خیلی از موارد ترکیبی از Cursor, While ,Temp Table ها مشاهده میشه ، کاملا مشخص هست که برنامه نویس داره الگوریتم فراخوانی اطلاعات هم به SQL Server تحمیل میکنه که کاری کاملا اشتباهه.
شما در SQL Server باید به این طریق کد بنویسید که نیازتون رو بیان کنید. همین
اینکه چطوری این داده ها فراخوانی می شوند رو به Engine SQL Server بسپارید . بهتون قول میدم به بهترین نحو و با بهترین الگوریتم ها ،‌اطلاعات موردنظر شمارو فراخوانی خواهد کرد و به شما نشان خواهد داد.

اگر در این خصوص سوالی داشتید در خدمتتون هستم.

ارادتمند.
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL
سلام و عرض ادب خدمت دوستان عزیزم
امیدوارم حالتون خوب باشه
بحثی رو چند روز اخیر شروع کردم د رخصوص Set Based نوشتن و سبب سوالات بسیار زیادی در خصوصی من شد که ابهام ایجاد شده بود که چطور خود SQL Server متوجه میشه راه درست چیه.؟
تصمیم گرفتم یک ذره ساده تر مساله رو توضیح بدم و با مثالهای متعدد این بحث رو جا بندازم.
خوب بذارید از یک مثال فارسی شروع کنیم.
ما میخواهیم ده تا کتاب رو از کتابخونه از سری کتابهای علمی بگیریم که رنگ جلد آنها زرده.

این رو میشه به دو صورت بیان کرد. من در دو حالت Set Based و Cursor Based بیانش میکنم تفاوت هاش رو ببینید و خودتون زمانش رو حدس بزنید.

قسمت Set Based :
در کتابخونه به قفسه کتابهای علمی برو(From ) و از فهرست اونجا نگاه کن کتابهایی که جلد زرد رنگ دارند(Where) ده عدد(Top) جداکن بردار.


قسمت Cursor Based :
با استفاده از تاکسی ها به کتابخونه برو. حتما سوار تاکسی های زرد بشو و از تاکسی های عبوری و اتوبوس استفاده نکن.
در کتابخونه از راهروی سمت راست برو به انتهای راهرو رسیدی بپیچ به سمت چپ و از پله ها بیا پایین به انتهای راهرو برو در اونجا قفسه کتابهای علمی رو مشاهده می کنی.
حالا از پایین قفسه تک تک کتابهارو بردار رنگشون رو بررسی کن اگر رنگ اونها زرده برش دار و بذار داخل سبد اگر رنگش زرد نبود کتاب رو بذار سرجاش برو سراغ کتاب بعدی. اینکار رو تکرار کن تا ده عدد کتاب با جلد زرد رنگ رو جمع آوری کنی.

خوب اختلاف رو دیدین؟
شما به SQL Server میگید چه چیزی نیاز دارید و از کجا و چه مشخصاتی داشته باشه. اینکه چطوری اون دیتاها فراهم بشه SQL Server به واسطه Statistics ها ، به واسطه ایندکس ها و موارد دیگه بهترین الگوریتم و سریعترین الگوریتم رو برای رسیدن به دیتای شما فراهم می کنه
ولی وقتی شما میاین مطابق روش دوم براش راه حل در نظر میگیرید سبب میشه دیگه از الگوریتم های خودش پیروی نکنه و هرچی شما دیکته کردین انجام بده پس مستلزم انجام مراحل خیلی بیشتر و مسلما زمان بیشتر و درگیری منابع بیشتر هست.

وقتی من در روش اول بیان نکردم چطور برو کتابخونه ، شاید اون فرد با BRT خیلی سریعتر برسه یا با مترو. ولی در روش دوم من اجبارش کردم حتما باید با تاکسی زرد بره. که میتونه ترافیک باشه و خیلی شلوغ باشه.

در پستهای بعدی مثالهای عملی تری رو ارائه می کنم
لطفا سوالات و نظراتتون رو بامن درمیان بذارید تا بتونم کیفیت مطالبی که مینویسم رو ارتقا بدم.

ارادتمندشما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server
#قسمت_دوم
سلام و عرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوب باشه
یک سری سوال در مورد T-SQL آماده کردم و تمایل دارم سطح دانش افراد کانال رو بسنجم که بتونم با دقت بیشتری مطالبی رو بنویسم و آموزشهایی رو تدوین کنم.
لذا خواهشی که از شما عزیزان دارم این هست که بدون اینکه در اینترنت سرچ کنید از دانش خودتون استفاده کنید و این سوالات رو پاسخ بدین و در یک فایل ورد برای من در خصوصی ارسال کنید. جواب سوالات رو نیز چند روز آتی قرار خواهم داد.
فقط جواب شما عزیزان به این سوالات برای من اهمیت داره که بتونم یک ارزیابی صحیحی داشته باشم.
پیشاپیش تشکر میکنم از همه عزیزانی که این سوالات رو بررسی می کنندو فرصتی رو قرار میدن و به این سوالات پاسخ میدن.

نکته : دوستان عزیزم توجه کنید که هدف من این هست که دقیقا بدونم در چه حوزه هایی بیشتر ضعف هست که بتونم روی اون موارد تمرکز بیشتری بکنم.
لذا پاسخ های شما بسیار برای من مهمه .

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
سلام و عرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوب باشه
تا به امروز فقط 4 نفر از عزیزان زحمت کشیدن پاسخ سوالات رو دادن.
من روز جمعه جوابهارو ارسال خواهم کرد. لذا خواهشمندم محبت کنید یک ساعت وقت بذارید و اگر مقدوره به این سوالات پاسخ بدین.
در سوالات نکات مهمی نهفته هست که پس از مشاهده پاسخ ها احتمالا مطالب جدیدی را فراخواهید گرفت
بی صبرانه منتظر لطف شما عزیزان هستم

ارادتمند
حمیدرضا صادقیان
سلام و عرض ادب خدمت دوستان عزیز
تعطیلات خوبی رو تا به این لحظه براتون آرزومندم
چند تن از عزیزان از من خواستند که زمان ارسال جواب رو مقداری به تاخیر بندازم.
من برای یکشنبه شب جوابها رو ارسال خواهم کرد و پارت بعدی سوالات که در خصوص DBA و مدیریت دیتابیس ها هست براتون ارسال می کنم.
تا به این لحظه اگر بخواهم جوابها رو یک آنالیز کلی بکنم باید عرض کنم که در خصوص مفاهیم اصلی SQL Server متاسفانه دانش کمی وجود داره.
و تقریبا در اکثر پاسخ ها مشاهده کردم که دوستان از امکانات جدید SQL Server اصلا اطلاعی ندارند و خیلی از مشکلات و مسائل رو با روشهای بسیار قدیمی سعی می کنند حل کنند.
خیلی از الگوریتهایی که برای حل مسائل پیشنهاد شده مبتدی و یک جورایی میشد گفت پیچیده بودند.
که در پاسخ سوالات این مباحث رو مطرح می کنم و توضیح میدم.
و سعی میکنم پیرامون این مسائل سلسله مفاهیمی رو توضیح بدم خدمتتون .
در این بین اگر در خصوص مسائل مطرح شده ، توضیحات ارائه شده ، مثالهای زده شده ، نظری پیشنهادی انتقادی هر چیزی هست بیان کنید.
اگر نوع نگارش متون سخته یا مثالها پیچیده هستند یا خیلی ساده هستند، یا هر اشکالی که احساس می کنید ممکنه درک مطالب رو دشوار کنه ، ممنون میشم بیان کنید که بتونم اصلاحشون کنم که از بهترین شیوه آموزشی بهره ببریم.

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
سلام وعرض ادب خدمت دوستان عزیزم
امیدوارم حالتون خوب باشه
در پست بعد جواب سوالات مربوط به پرسشها را قرار میدم.
ممنون از همه عزیزانی که محبت کردن و وقت گذاشتن و به این پرسشها پاسخ دادن.

ممنونم از اینکه با نظرات ارزشمندتون کمک می کنید کیفیت مطالب افزایش پیدا کنه

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server #Quiz #Quiz_Answer
سلام و عرض ادب خدمت دوستان عزیزم
امیدوارم حال همه شما خوب و خوش باشه و براتون سلامتی و شادی آرزومندم
همونطور که میدونید در دو پست قبلی در خصوص Set Based Thinking صحبت کردم و مثال هایی رو عرض کردم.
امروز قصد دارم مقداری وارد مسائل حقیقی بشیم که باهاش سرو کار داریم.
خوب من مساله ای رو مطرح می کنم خوشحال میشم راه حل هاتون رو در خصوصی برای من ارسال کنید.
پیشاپیش از همه عزیزانی که در این سوال و جوابها شرکت می کنند تشکر میکنم چون باعث میشه انگیزه بیشتری پیدا کنم و زمان بیشتری رو صرف کنم که این مسائل جا بیافته.
متاسفانه در دانشگاهها و موسسات آموزشی اصلا به این موارد نمی پردازند. بعضی از اساتید دانشگاهها متاسفانه اصلا از دانش خوبی در این حوزه برخوردار نیستند و اگر همین مسائل رو بپرسید به سختی میتونند بهتون پاسخ بدن. همین مسائلی که من اینجا مطرح میکنم از اساتیدی که میشناسید بپرسید و پاسخهای آنها رو با جوابهایی که اینجا ارسال میشه مقایسه کنید تا خودتون به عمق فاجعه پی ببرید.
خوب برگردیم سر سوال.
یکی از مسائلی که در نرم افزارها با آن مواجه هستیم بحث پیدا کردن شماره های خالی یا Gap بین شماره اسناد یا شماره نامه ها هست
فرض کنید داده های زیر رو دارید.
Id
1
2
3
5
6
8
10
15
21
30
45
46
47
48
49
50
55
56
57
58
60
61
62
66

ما میخواهیم شماره اسنادی رو بدست بیاریم که داخل این لیست نیستند.
که جواب باید به شرح زیر باشه
4,7,9,11..14,16..20,22..29,31..44,51..54,59,63,64,65

جوابها رو تا روز یکشنبه آخروقت برای من ارسال کنید
من راه حل های مختلف رو روز دوشنبه قرار میدم و کامل دراین زمینه شرح میدم.
لطفا از اینترنت کدی برای من کپی نکنید ارسال کنید.خیلی ارزشمند نیست. میخوام خودتون بشینید به سوال فکر کنید و با دانش خودتون و مطالبی که در پرسش و پاسخ ها و پستهای قبل عرض کردم راه حل برای من بنویسید. وگرنه الان دنبال مساله Gap در اینترنت بگردید راه حلهای زیادی رو پیدا می کنید.
منتظر پاسخهای شما عزیزان هستم.
(خوشحال میشم اتفاقا از اساتید دانشگاهی که میشناسید بپرسید و راه حل های این عزیزان هم بیارید باهم بررسی کنیم☺️)

اسکریپت ساخت جدول :
Create Table #Test (Id int)
Go
Insert into #Test
Values(1),(2),(3),(5),(6),(8),(10),(15),(21),(30),(45),(46),(47),(48),(49),(50),
(55),(56),(57),(58),(60),(61),(62),(66)
Go

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server #Learn_SQL_Server
#قسمت_سوم
سلام و عرض ادب خدمت عزیزان و دوستان گرامی
امیدوارم که حالتون خوب باشه
قبل از هرچیزی جاداره از تمام دوستان عزیزی که محبت کردن و پاسخ هارو ارسال کردن تشکر کنم.
البته این مساله خیلی ساده بود و اصلا من قسمتهای پیچیده اوونو مطرح نکردم که سبب نوشتن کدهای سنگین بشه.
فقط صرفا هدف آشنایی با مفاهیم Set Based هست و اینکه مفهوم کدهارو متوجه بشیم.
تابع زیر برای تولید اعداد هست که تا یک بازه بزرگی رو تولید می کنه.

CREATE FUNCTION dbo.GetNums(@low AS BIGINT, @high AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS (SELECT c FROM (SELECT 1 UNION ALL SELECT 1) AS D(c)),
L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM L5)
SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
FROM Nums
ORDER BY rownum;
GO

من سه تا کد مختلف نوشتم که هر کدومش رو توضیح میدم.
کد اول :

Select n as ID from Getnums(1,66) as n
where not exists(Select * from #test as d where n.n=d.id)
در این کد من با استفاده از تابع فوق اعداد 1 تا 66 رو تولید کردم و بایک Not exists دارم چک میکنم که رکورد وجود داره یا نه. به این طریق نوشتن Select در Where Clause که سبب ارتباط با Select بالایی هست Correlated subquery می گویند.
این کد رو با not in هم می تونید بنویسید ولی performance ضعیفتری نسبت به این کد داره. در اینجا اعداد 1 تا 66 ایجاد شده و براساس شرط داخلی سلکت در Where چک می شود که آیا رکورد فوق True هست یا False . به همین خاطر از سرعت پردازش بالایی برخورداره .
روش دوم :
Select n as ID from Getnums(1,66) as n
except
Select Id from #test

در این روش یک مرحله اضافه وجود داره و این هم بحث Sort و Distinct هست که خود عملیات Except سبب اون خواهد شد و باعث میشه نسبت به کد بالایی از Performance پایین تری برخوردار باشه.

روش سوم :
Select n as ID from Getnums(1,66) as n
Left outer Join #test as d
on n.n=d.id
where d.id is null

این روش هم نسبت به روش اول تقریبا کندتر هست .
الان خیلی نمیخوام وارد جزئیات مسائل Performance بشم.
باز هم تاکید میکنم مساله رو هم ساده انتخاب کردم هم روشهای ساده ای نوشتم که با طرز تفکر Set Based در مسائل مختلف آشنا بشین. جلوتر که بریم مسائل پیچیده تر و منطق های پیچیده تری رو حتما بررسی می کنیم و هم اینکه نکات Performance رو عرض می کنم.

با روشهای Cursor Based هم بخواهید بنویسید میشه با یک حلقه چک کرد ببینیم آیا رکورد فوق موجود هست یاخیر که نسبت به این روشها کندتر خواهد شد.

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server #Learn_SQL_Server
#قسمت_چهارم
👍2