PDA

View Full Version : کویری که اولین رکورد هر شماره چرستل رو برگردونه



rezaei manesh
چهارشنبه 09 اسفند 1385, 08:47 صبح
سلام
من یک کویری نوشتم که رکورد ها رو برای هر پرسنل در یک محدوده تاریخ هست رو مرتب می کنه و برمیگردونه حالا من می خوام این کویری یه فیلتر دیگه هم بشه یعنی فقط اولین رکورد هر پرسنل را برگردونه
برای مثال اگه داده ها به این شکل باشند

PerNo =1 - sdate=01/01 EDate=12/29-section=2
PerNo =1 - sdate=01/20 EDate=01/29-section=3

PerNo =2 - sdate=01/01 EDate=12/29-section=6
PerNo =2 - sdate=01/21 EDate=01/25-section=5
اکنون باید داده های بالا برای هر پرسنل صعودی مرتب بشه و بعد اولین رکورد برداشته بشه به این صورت(برای تاریخ 01/25)

PerNo =1 - sdate=01/20 EDate=01/29-section=3
PerNo =2 - sdate=01/21 EDate=01/25-section=5
کد کویری من هم رو پایین می زارم اگه میشه یه نگاه بندازید راه حل در این چنین مواقعی چی هست.


SELECT LTRIM(PERNO) AS perno, [SECTION], SDATE
FROM dbo.MyTable
WHERE (sDATE >= '01/24') AND (Edate <= '01/24')
ORDER BY LTRIM(PERNO), EDATE DESC

whitehat
چهارشنبه 09 اسفند 1385, 10:45 صبح
یعنی فقط اولین رکورد هر پرسنل را برگردونه
منظورتان از اولین چیه؟ بالاخره بر اساس فیلدی باید این Query مرتب شود. بر اساس آن فیلد نمی توانید اولین فیلد را بدست بیاورید؟ (مثلا اونی که بیشترین تاریخ را دارد) بهتره فیلد های جدول را بنویسید :)

rezaei manesh
چهارشنبه 09 اسفند 1385, 11:00 صبح
منظورتان از اولین چیه؟ بالاخره بر اساس فیلدی باید این Query مرتب شود. بر اساس آن فیلد نمی توانید اولین فیلد را بدست بیاورید؟ (مثلا اونی که بیشترین تاریخ را دارد) بهتره فیلد های جدول را بنویسید :)

فیلد های sdate و pernoدر جدول کلید هستند
حال من می خوام برای هر perno یک رکورد داشته باشم اما رکوردی که تاریخ xی که (که این تاریخ از یه جدول دیگه لینک باید بشه) به اون داده می شه بین تاریخ های sdate و edate باشه و اگر تعداد رکورد های خروجی بیش از یک بود اونی رو بده که sdate اون بزرگتره
در کل این کوئری من باید با چند تا جدول دیگه هم لینک بشه یه جورایی این هسته بقیه کوئری هام هست .
در همون کوئری بالا اگه من یه Top 1 و یک where perno=2 بدم رکورد رو برای این پرسنل درست می ده اما می نمی دونم حالا همون چکار کنم که برای همه پرسنل عمل کنه

سید مسعود موحد
چهارشنبه 09 اسفند 1385, 11:16 صبح
من فکر کنم که با کد زیر بشود اگر منظورتون رو درست متوجه شده باشم



SELECT LTRIM(PERNO) AS perno, [SECTION] , Max(SDATE)
FROM dbo.MyTable
WHERE (sDATE >= '01/24') AND (Edate <= '01/24')
ORDER BY LTRIM(PERNO), EDATE DESC
Group By PERNO, [SECTION]

rezaei manesh
چهارشنبه 09 اسفند 1385, 11:37 صبح
سلام
دستت درد نکنه مسعود جون
اما کویری شما هم جواب نمی ده چون اگه (max(SDate رو که تو خروجی می زاری مجبوری تو گروپ هم بزاری در ضمن می خوام خروجی نهایی من تنها شامل یک رکورد برای هر شماره پرسنلی باشه کد بدونم در اون تاریخ کدوم section رو داره اگه با section هم گروپ کنم...

whitehat
چهارشنبه 09 اسفند 1385, 11:59 صبح
باز هم اسامی فیلد ها و جداول را ننوشتید! با این حال با توضیحی که دادید من فرض می کنم که لینک جدول تاریخ و جدول اصلی همان Perno هست


Select * From
MyTable
Left Outher Join
(
Select perno, [SECTION] , Max(SDATE) from YourDateTable
Where (sDATE >= '01/24') AND (Edate <= '01/24')
Group By PERNO, [SECTION]
ORDER BY LTRIM(PERNO), EDATE DESC) As DateTable
On myTable.Perno=DateTable.Perno

rezaei manesh
چهارشنبه 09 اسفند 1385, 13:35 عصر
من نتونستم منظور شما رو بفهمم لطفا بیشتر توضیح بدین
شکل جدول ها رو در تصویر زیر کشیدم
اون تاریخی که باید بر اساس او در جدول حکم ها آخرین حکم فعال پیدا بشه IOInfo.BEGINDATE و لینک دوتا جدول بر اساس شمار ه پرسنل و تاریخ هست

whitehat
چهارشنبه 09 اسفند 1385, 14:36 عصر
یعنی شما الان می خواهید مثلا برای 31 رکورد آخر قسمتی که Highlight کردید را برگردانید ؟

rezaei manesh
چهارشنبه 09 اسفند 1385, 14:52 عصر
می خوام برای هر تاریخ از جدول ioinfo کد قسمتی رو که تو اون تاریخ کار می کرده رو برگردونم
کد قسمت هم توی PrjRule هست
الان یه عکس دیگه هم از همه حداول درگیر درست می کنم

rezaei manesh
چهارشنبه 09 اسفند 1385, 15:22 عصر
اینم عکس ها از جدول ها و کوئریم
الان بازای هر رکورد در PrjRuleیک رکورد در خروجی داریم که نباید این طور باشه باید به نحوی تاریخ رو هم درگیر کنیم

MM_Mofidi
چهارشنبه 09 اسفند 1385, 15:40 عصر
چرا از top استفاده نمیکنی

rezaei manesh
چهارشنبه 09 اسفند 1385, 15:53 عصر
top 1 گذاشتم و برای یک Perno درست کار می کنه اما وقتی همه Perno رو میدم بدون فیلتر با جوین باز فقط یک رکورد رو در خروجی دارم

whitehat
چهارشنبه 09 اسفند 1385, 16:11 عصر
من فقط Query مربوط بدست آوردن آخرین رکورد هر PerNo را می نویسم Join با خودتان.بعد از آن می توانید با هر جدولی که خواستید Join کنید


Select * From
IoInfo Inner Join
(Select PerNo,Max(BeginDate) As MyBeginDate
From IOInfo Group By PerNo) As TempTable1
on (MyBeginDate=IoInfo.BeginDate And IoInfo.PerNO=TempTable1.PerNo)
البته این درصورتی که BeginDate منحصر به فرد باشه در غیر این صورت Max زمان را هم اضافه کنید(برای بهینه کردن هم می توانید از Hashکردن کلید استفاده کنید)

rezaei manesh
چهارشنبه 09 اسفند 1385, 19:21 عصر
با تشکر از وقتی که برام گذاشتید
من مشکلم رو با روش دیگه ای حل کردم یعنی دیگه مستقیم جویند نکردم برای هر پرسنل جدا این کار رو کردم برای کاری که فعلا دارم خوب هست چون هر بار برای یک ماه رو فقط حساب می کنند اونم برای یه عده ای خاص -اما من می خوام روش رو برای اینچنین مواردی رو پیداکنم
کوئری شما 2 خطا زیرمیده


Server: Msg 156, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'on'.
Server: Msg 156, Level 15, State 1, Line 5
Incorrect syntax near the keyword 'As'.

اما به هر حال من نمی خوام آخرین رکورد هر پرسنل رو تو جدول ورود و خروج داشته باشم که من برای هر تاریخ تویه ورود و خروج می خوام حکم فعال اون تاریخ رو تو جدول PRjRule داشته باشم
begindate و begintime و perno سه فیلد کلیدی Ioinfo هستند .
من تو همون پست های اول کد حکم فعال رو برای هر پرسنل گذاشتم شما فقط باید اونو به جدول
IOINFO متصل کنیم و پارامتر های perno و تاریخ اونو مقدار بدیم

اگه ممکنه در مورد HAsh کردن هم توضیح بدین

whitehat
چهارشنبه 09 اسفند 1385, 19:58 عصر
خواهش می کنم http://qsmile.com/qsimages/236.gif
کوئری را در ست کردم (البته امیدوارم) من یک Space بین Temp و Table گذاشته بودم. چون داده ای ندارم تست کنم نمی دانم درست جواب می دهد یا نهhttp://qsmile.com/qsimages/162.gif

من برای هر تاریخ تویه ورود و خروج می خوام حکم فعال اون تاریخ رو تو جدول PRjRule داشته باشم
با توجه به اینکه PerNo کلید اصلی هست پس باید عمل Join با این فیلد انجام بشه و با توجه به اینکه شما نیاز دارید برای هر PerNo فقط یک فیلد از جدول ورود خروج بدست بیاورید پس باید قبل از عمل Join این رکورد را بیابید.که Query بالایی این کار را انجام می دهد.بعد آنرا با PrjRule براساس کلید اصلی Join کنید. این همان چیزی است که در پست اول برای Join نوشتید.فقط آن کوئری با یک رکورد می تواند کار کند.
راه حل آخر برای این کار می تونه استفاده از یک Sp باشه که کرسری تک تک کوئری قبلی شما را اجرا کرده و نتیجه را ذخیره می کنه.


اگه ممکنه در مورد HAsh کردن هم توضیح بدین
بعضی مواقع لازم هست بر اساس چند کلید عمل Join انجام بشه که می توانید همه را در قالب یک کلید Hash کنید و با هم Join کنید.
موفق باشید

rezaei manesh
پنج شنبه 10 اسفند 1385, 10:09 صبح
سلام
نمی دونم چطور از وقتی که میزارید تشکر کنم
اما بازهم همون خطا رو میده


Select * From
IoInfo Inner Join
on (MyBeginDate=IoInfo.BeginDate And IoInfo.PerNO=Table1.PerNo)
(Select PerNo,Max(BeginDate) As MyBeginDate From IOInfo Group By PerNo) As Temp Table1

بازم بگم من امکان داره یه تاریخ رو چند بار تویه ioinfo برای هر پرستل داشتم باشم چون امکان داره چندبار کارت بزنه و برای هر بار من باید عملیات رو چک کنم
حالا مشکل من در این مورد به نحوی حل شده
لطفا کلی بگین که همچین مواقعی باید چه نکاتی رو رعایت کنیم

whitehat
پنج شنبه 10 اسفند 1385, 11:29 صبح
من کوئری را اصلاح کرده بودم ! این همون قبلی هست :)



Select * From
IoInfo Inner Join
on (MyBeginDate=IoInfo.BeginDate And IoInfo.PerNO=Table1.PerNo)
(Select PerNo,Max(BeginDate) As MyBeginDate From IOInfo Group By PerNo) As Temp Table1
دوجایی که قرمز کردم را اصلاح کنید. قسمت اول باید بشه TempTable و قسمت دوم باید Space حذف بشه و جای خط آخر با ماقبل آخر عوض بشه

بازم بگم من امکان داره یه تاریخ رو چند بار تویه ioinfo برای هر پرستل داشتم باشم چون امکان داره چندبار کارت بزنه و برای هر بار من باید عملیات رو چک کنمخب باید بگم که من تاحالا برعکس فکر می کردم ! با این حساب بهتره که آخرین رکورد پرسنل را در جدول PrjRule بدست بیاورید و بعد با جدول ورود خروج Join کنید.می توانید از همان کئری بالا استفاده کنید یعنی یک بار بر اساس آخرین تاریخ در جدول اول Perno ها را بیابید ، سپس با خودش Joinکنید.مثلا یه همچین چیزی


Select * from
PrjRule Inner Join
(Select PerNo,Max(BeginDate) As MyBeginDate
From PrjRule Group By PerNo) As MyPrjRule
On (MyPrjRule.PerNo=PrjRule.PerNo And PrjRule.BeginDate=MyPrjRul.MyBeginDate)
بعد آنرا با IOInfo متصل(Join) کنید.اگر دیدید کوئری بالا رکورد تکراری (عینا شبیه هم) می دهد در Select درونی Distinct اضافه کنید.

لطفا کلی بگین که همچین مواقعی باید چه نکاتی رو رعایت کنیممعمولا زمانی که شما رابطه N<--->M دارید بهتر است از یک جدول میانی استفاده کنید که روابط در آن ذخیره می شود. اینجوری حجم کوئری ها نیز کمتر می شود.در غیر این صورت مجبورید ای کوئری های این چنینی استفاده کنید
موفق باشید