PDA

View Full Version : سوال: انتخاب رکوردهایی که جمع مقادیر آنها مساوی است با



فؤاد
یک شنبه 30 خرداد 1389, 20:18 عصر
سلام

جدولی دارم با فیلدهای زیر

ID int
Score int

میخواهم تعدادی از رکوردهای این جدول انتخاب کنم که جمع فیلد Score آنها مساوی با N شود.
برای من مهم نیست کدام رکوردها انتخاب شوند مهم این است که جمع رکوردهای انتخاب شده با N مساوی باشد.

با تشکر

mohsensaghafi
یک شنبه 30 خرداد 1389, 21:05 عصر
سلام دوست عزیز.
برای این کار باید تو برنامه که به این وصل می شه این کار رو بکنی یا از Store Procedure استفاده کنی.

pezhvakco
یک شنبه 30 خرداد 1389, 21:34 عصر
درود :
اینو امتحان کن :

SELECT ID
FROM (SELECT ID, SUM(Score) AS Expr1
FROM Table1
GROUP BY ID) T1
WHERE (Expr1 = 5)

فکر خوش .

فؤاد
دوشنبه 31 خرداد 1389, 00:51 صبح
درود :
اینو امتحان کن :

SELECT ID
FROM (SELECT ID, SUM(Score) AS Expr1
FROM Table1
GROUP BY ID) T1
WHERE (Expr1 = 5)

فکر خوش .

سلام

امتحان کردم - جواب نداد ولی !!!!

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 00:52 صبح
درود :
اینو امتحان کن :

SELECT ID
FROM (SELECT ID, SUM(Score) AS Expr1
FROM Table1
GROUP BY ID) T1
WHERE (Expr1 = 5)

فکر خوش .

سلام،
چرا از جدول مشتق شده (derived table) استفاده کردین؟ میتونستید فیلتر را با HAVING انجام بدین.
میشه کد را ساده تر و خوانا تر کرد. البته اگر می خواهین تمام سطرهای مربوط به ID هایی که جمع Score های آنان برابر با N است را بدست آورین، در آخرسر بایستی JOIN کنید با جدول یعنی :

SELECT ID, Score
FROM (SELECT ID
FROM table
GROUP BY ID
HAVING SUM(Score) = @N) D
JOIN table t
ON D.ID = t.ID

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 01:00 صبح
سلام

امتحان کردم - جواب نداد ولی !!!!

روشی را که در پست قبلیم به آن اشاره کردم (داخل تگ کد قرار دادم) را امتحان کنید
اگر جواب نداد، بگین که از نظر منطقی آن نتیجه ی مطلوب شما را برنگرداند یا اینکه یک error ارسال شد. و همچنین یک نمونه از داده های جدول همراه با نتیجه ی مطلوب را ارسال کنید.

فؤاد
دوشنبه 31 خرداد 1389, 01:02 صبح
سلام،
چرا از جدول مشتق شده (derived table) استفاده کردین؟ میتونستید فیلتر را با HAVING انجام بدین.
میشه کد را ساده تر و خوانا تر کرد. البته اگر می خواهین تمام سطرهای مربوط به ID هایی که جمع Score های آنان برابر با N است را بدست آورین، در آخرسر بایستی JOIN کنید با جدول یعنی :

SELECT ID, Score
FROM (SELECT ID
FROM table
GROUP BY ID
HAVING SUM(Score) = @N) D
JOIN table t
ON D.ID = t.ID

سلام

از شما هم سپاسگذارم - ولی خطا داد !!!!

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 01:05 صبح
سلام

از شما هم سپاسگذارم - ولی خطا داد !!!!

چه پیغام خطایی داد؟
آیا نام جدولتان را با کلمه ی table که در کوئری نوشتم جابجا کردین؟

فؤاد
دوشنبه 31 خرداد 1389, 01:12 صبح
روشی را که در پست قبلیم به آن اشاره کردم (داخل تگ کد قرار دادم) را امتحان کنید
اگر جواب نداد، بگین که از نظر منطقی آن نتیجه ی مطلوب شما را برنگرداند یا اینکه یک error ارسال شد. و همچنین یک نمونه از داده های جدول همراه با نتیجه ی مطلوب را ارسال کنید.


خطا نداد - جواب مورد نظرم رو برنگردوند



ُID Score
--------------
1 1
2 3
3 4
4 2

فرض کنید میخواهم رکوردهایی از این جدول انتخاب شود که جمع فیلد Score آنها 5 باشد (مثلا رکوردهای 1 و 3 را برگرداند)

مرسی

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 01:33 صبح
فرض کنید عدد مطلوب شما 6 باشد. در این حالت چه سطرهایی از جدول باید انتخاب بشوند؟ 1و2و4 یا 3و4
اگر عدد مورد نظر شما 11 باشد آیا سطری انتخاب می شود؟ با اینکه مجموع کل Score ها برابر با 10 خواهد بود

یک الگوریتم که فکر می کنم ساده ترین باشه به قرار زیر هست:
ابتدا Power Set مجموعه را بدست بیاریم با کمک Recursive CTE (اگر از اسکیول 2005 و بالاتر استفاده می کنید) سپس هر عضوی از این Power Set (که برای خودش زیر مجموعه ای محسوب میشه) که مجموع عناصرش برابر با عدد مورد نظر هست را انتخاب کنیم.

بطور مثال Power Set سطرهایی که بطور نمونه در پستتان قرار دادین به قرار زیر است:
1
1و2
1و2و3
1و2و3و4
1و3
1و4
2و3
3و4
1و2و4
1و3و4
و ...

که تعداد این عناصر برابر با 16 است یعنی 2 به توان 4.

اگر از 2005 یا بالاتر استفاده می کنید بگید تا برایتان کوئری را خلق کنم.

فؤاد
دوشنبه 31 خرداد 1389, 01:59 صبح
چه پیغام خطایی داد؟
آیا نام جدولتان را با کلمه ی table که در کوئری نوشتم جابجا کردین؟

بله

Ambiguous column name 'ID'.

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 02:10 صبح
:اشتباه:

SELECT t.ID, Score
FROM (SELECT ID
FROM table
GROUP BY ID
HAVING SUM(Score) = @N) D
JOIN table t
ON D.ID = t.ID

فؤاد
دوشنبه 31 خرداد 1389, 02:24 صبح
فرض کنید عدد مطلوب شما 6 باشد. در این حالت چه سطرهایی از جدول باید انتخاب بشوند؟ 1و2و4 یا 3و4
اگر عدد مورد نظر شما 11 باشد آیا سطری انتخاب می شود؟ با اینکه مجموع کل Score ها برابر با 10 خواهد بود

یک الگوریتم که فکر می کنم ساده ترین باشه به قرار زیر هست:
ابتدا Power Set مجموعه را بدست بیاریم با کمک Recursive CTE (اگر از اسکیول 2005 و بالاتر استفاده می کنید) سپس هر عضوی از این Power Set (که برای خودش زیر مجموعه ای محسوب میشه) که مجموع عناصرش برابر با عدد مورد نظر هست را انتخاب کنیم.

بطور مثال Power Set سطرهایی که بطور نمونه در پستتان قرار دادین به قرار زیر است:
1
1و2
1و2و3
1و2و3و4
1و3
1و4
2و3
3و4
1و2و4
1و3و4
و ...

که تعداد این عناصر برابر با 16 است یعنی 2 به توان 4.

اگر از 2005 یا بالاتر استفاده می کنید بگید تا برایتان کوئری را خلق کنم.


بله از اس کیو ال سرور 2005 استفاده میکنم - ممنون میشم اگه لطف کنید - پیشاپیش یکدنیا تشکر

pezhvakco
دوشنبه 31 خرداد 1389, 08:49 صبح
میتونین جدول رو این جا قرار بدین .

فکر خوش .

فؤاد
دوشنبه 31 خرداد 1389, 11:23 صبح
میتونین جدول رو این جا قرار بدین .

فکر خوش .

در پست های قبلی هم ساختار جدول هست و هم اطلاعات فرضی

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 14:10 عصر
ببینید این نتیجه مناسب هست؟


Declare @t table (id int, score int)
insert @t select 1, 1
union select 2, 3
union select 3, 4
union select 4, 2;

select * from @t
/*
id score
----------- -----------
1 1
2 3
3 4
4 2
*/

;WITH RecCTE AS
(
SELECT Convert(VarChar(30),id) id, score
FROM @T
UNION ALL
SELECT Convert(Varchar(30),cast(t2.id as varchar(10)) + ',' + cast(t3.id as varchar(10))) as id, t2.score + t3.score as score
FROM @T T2
CROSS JOIN RecCTE T3
WHERE cast(t2.id as varchar(10)) <> t3.id
AND t2.id < LEFT(t3.id,charindex(',',t3.id+',')-1)
)
SELECT * FROM RecCTE
WHERE score = 5
/*
id score
------------------------------ -----------
2,4 5
1,3 5
*/

فؤاد
دوشنبه 31 خرداد 1389, 15:35 عصر
ببینید این نتیجه مناسب هست؟


Declare @t table (id int, score int)
insert @t select 1, 1
union select 2, 3
union select 3, 4
union select 4, 2;

select * from @t
/*
id score
----------- -----------
1 1
2 3
3 4
4 2
*/

;WITH RecCTE AS
(
SELECT Convert(VarChar(30),id) id, score
FROM @T
UNION ALL
SELECT Convert(Varchar(30),cast(t2.id as varchar(10)) + ',' + cast(t3.id as varchar(10))) as id, t2.score + t3.score as score
FROM @T T2
CROSS JOIN RecCTE T3
WHERE cast(t2.id as varchar(10)) <> t3.id
AND t2.id < LEFT(t3.id,charindex(',',t3.id+',')-1)
)
SELECT * FROM RecCTE
WHERE score = 5
/*
id score
------------------------------ -----------
2,4 5
1,3 5
*/


سلام - بابت وقتی که گذاشتین خیلی ممنونم - برای من که در حال حاضر جدولم 25000 رکورد داره این کوئری خیلی کند عمل میکنه و عملا .... با این حال از بذل محبت شما خیلی ممنونم

پایدار و سلامت باشید

محمد سلیم آبادی
دوشنبه 31 خرداد 1389, 15:59 عصر
حق با شماست. اگر به خاطر داشته باشید در یکی از پستهای قبلی اشاره کردم این ساده ترین و مطمئنا بدترین الگوریتم ممکنه است که من سراغ داشتم و با آن آشنا هستم.
اگر جدول شما n تا سطر داشته باشد n بار عمل JOIN صورت می گیرد که خیلی هزینه بر هست. و همچنین تعداد سطری که بر گردانده می شود برابر با 2 به توان n هست که باید یک عدد Huge ای باشه!!

چون این مساله یک چالش واقعی برایم ایجاد کرد دوست دارم براش یک راه حل مناسب و مطلوبی را بدست بیارم. اگر تونستم، از افراد به نام در جهان مثل Itzik Ben Gan سوال می کنم و در صورت بدست آوردن جواب به شما اطلاع می دم.