PDA

View Full Version : استفاده از NEWID با تاثير پذيري از يه فيلد ديگر



mehrdad_shahian
سه شنبه 17 اسفند 1389, 11:19 صبح
سلام

من از Newid در انتخاب ركوردهاي تصادفي استفاده كردم.ولي ميخام از يه فيلد ديگه اي به نام rank تاثير بگيره.به گونه اي كه هرچهقدر اين فيلد حاوي مقدار بيشتري باشه،تعدادباري كه به عنوان ركورد اول انتخاب ميشه هم بيشتر باشه.براي مثال سه ركورد داريم كه فيلد rank انها به ترتيب حاوي 10 20 50 ؛حالا من كدي ميخام كه اين سه ركورد رو به صورت تصادفي انتخاب كنه و ركورد سوم كه حاوي 50 است رو بيشتر از دو ركورد ديگر به عنوان ركورد اول بياره

اميدوارم كه درست توضيح داده باشم

با تشكر پيشاپيش

Reza_Yarahmadi
سه شنبه 17 اسفند 1389, 13:44 عصر
میتونید بصورت زیر عمل کنید.
برای هر رکورد احتمال تجمعی اونو حساب کنید (بر اساس فیلد Rank). بعد یک عدد رندم بین 0 و بیشترین احتمال تجمعی بزنید. در نهایت یک Select روی جدول بزنید که اولین رکوردی که دارای احتمال تجمعی بیشتر از عدد تصادفی است برگردونه.
چیزی شبیه نمونه کد زیر
Create Table TableName(
Id int,
Rank int,
Name varchar(50))

Insert TableName Values(1, 10, 'Name1')
Insert TableName Values(2, 20, 'Name2')
Insert TableName Values(3, 30, 'Name3')
Insert TableName Values(4, 40, 'Name4')
Insert TableName Values(5, 50, 'Name5')


Declare @SumRank bigint, @Rand bigint
Select @SumRank = Sum(Rank) From TableName
Set @Rand = Rand() * @SumRank

;With res (id, Rank, Name, Aptness) as(
Select Top 1
Id,
Rank,
Name,
Rank as Aptness
From TableName
Order By Id
UNION ALL
Select
t.Id,
t.Rank,
t.Name,
t.Rank + res.Aptness as Aptness
From TableName t, res
Where t.Id = res.id + 1
)
Select TOP 1 *
From res
Where Aptness> @Rand
Order by Aptness


Drop Table dbo.TebleName

mehrdad_shahian
شنبه 21 اسفند 1389, 09:44 صبح
سلام
من اين كد رو براي استفاده تو ديتابيس خودم تغييردادم ولي هيچ ركوردي بر نميگردونه؛به نظرتون علتش چيه؟
Declare @SumRank bigint, @Rand bigint
Select @SumRank = Sum([Customer_Rank]) From [Customers].[dbo].[IranianBoyCustomer]
Set @Rand = Rand() * @SumRank

;With res ([Customer_id], [Customer_Rank], Aptness) as(
Select Top 1
[Customer_id]
,[Customer_Rank]
,Customer_Rank as Aptness
From [Customers].[dbo].[IranianBoyCustomer]
Order By [Customer_id]
UNION ALL
Select
t.Customer_id
,t.Customer_Rank
,t.Customer_Rank + res.Aptness as Aptness
From [Customers].[dbo].[IranianBoyCustomer] t, res
Where t.Customer_id = res.Customer_id + 1
)
Select TOP 1 *
From res
Where Aptness> @Rand
Order by Aptness

Reza_Yarahmadi
شنبه 21 اسفند 1389, 11:50 صبح
به نظر کد مشکلی نداره ، شاید داده های ذخیره شده مشکلی توشون هست(احتمالا یکی از Rankها مقدارش Null است)
دستور رو بصورت زیر تغییر بدید

Declare @SumRank bigint, @Rand bigint
Select @SumRank = Sum(ISNULL([Customer_Rank], 0)) From [Customers].[dbo].[IranianBoyCustomer]
Set @Rand = Rand() * @SumRank

;With res ([Customer_id], [Customer_Rank], Aptness) as(
Select Top 1
[Customer_id]
,[Customer_Rank]
,ISNULL(Customer_Rank, 0) as Aptness
From [Customers].[dbo].[IranianBoyCustomer]
Order By [Customer_id]
UNION ALL
Select
t.Customer_id
,t.Customer_Rank
,ISNULL(t.Customer_Rank, 0) + res.Aptness as Aptness
From [Customers].[dbo].[IranianBoyCustomer] t, res
Where t.Customer_id = res.Customer_id + 1
)
در صورتیکه با این تغییر بازم جواب نداد قبل دستور With مقدار متغیر Rand رو چک کنید ببینید مقدار داره یا نه ، و یا Select آخر رو بدون شرط خاصی بنویسید و ببینید احتمال تجمعی به درستی حساب شده یا نه

mehrdad_shahian
شنبه 21 اسفند 1389, 12:15 عصر
من همه كاري كردم ولي باز هيچ ركوردي بر نمي گردونه،تعداد ركورد ها 10 تا بيشتر نيست.شما ميگيد چيكار كنم؟؟؟ ميخايد كل جدول رو در اختيارتون قرار بدم و شما يه تستي روش انجام بديد.ميدونم توقع زياديه ولي لطف كنيد و به من كمك كنيد.كارم فوريه
راستي من اون كارايي كه گفتيد(قبل دستور With مقدار متغیر Rand رو چک کنید ببینید مقدار داره یا نه) رو بلد نيستم امجام بدم؛ چون زياد با محيط sql server اشنا نيستم.
متشكرم

Reza_Yarahmadi
شنبه 21 اسفند 1389, 16:18 عصر
ميخايد كل جدول رو در اختيارتون قرار بدم و شما يه تستي روش انجام بديد
hاگه بتونید یک اسکریپت از جدول و داده های اون بهم بدید راحتتر میشه کمکتون کرد. در صورتی که با نحوه تهیه اسکریپت آشنا نیستید یک بک آپ از دیتا بیس اینجا بذارید (در صورتیکه از SQL Server 2005 استفاده میکنید)

راستي من اون كارايي كه گفتيد(قبل دستور With مقدار متغیر Rand رو چک کنید ببینید مقدار داره یا نه) رو بلد نيستم امجام بدم؛ چون زياد با محيط sql server اشنا نيستم.
توی SQL Server یک New Query درست کنید و دستور زیر رو اجرا کنید ببینید چه مقدارهایی به عنوان خروجی نمایش داده میشه.
Declare @SumRank bigint, @Rand bigint
Select @SumRank = Sum(ISNULL([Customer_Rank], 0)) From [Customers].[dbo].[IranianBoyCustomer]
Set @Rand = Rand() * @SumRank
Select @Rand as Rand

;With res ([Customer_id], [Customer_Rank], Aptness) as(
Select Top 1
[Customer_id]
,[Customer_Rank]
,ISNULL(Customer_Rank, 0) as Aptness
From [Customers].[dbo].[IranianBoyCustomer]
Order By [Customer_id]
UNION ALL
Select
t.Customer_id
,t.Customer_Rank
,ISNULL(t.Customer_Rank, 0) + res.Aptness as Aptness
From [Customers].[dbo].[IranianBoyCustomer] t, res
Where t.Customer_id = res.Customer_id + 1
)
Select * From res Order by Aptness

mehrdad_shahian
شنبه 21 اسفند 1389, 17:01 عصر
h
اگه بتونید یک اسکریپت از جدول و داده های اون بهم بدید راحتتر میشه کمکتون کرد. در صورتی که با نحوه تهیه اسکریپت آشنا نیستید یک بک آپ از دیتا بیس اینجا بذارید (در صورتیکه از SQL Server 2005 استفاده میکنید)
[
3.5 مگ هستش؛اشكال نداره؟؟


h
توی SQL Server یک New Query درست کنید و دستور زیر رو اجرا کنید ببینید چه مقدارهایی به عنوان خروجی نمایش داده میشه.
[

خروجي :
Rand
134
-------------
customer_id customer_rank aptness
1 10 10
2 20 30
3 30 60

l

Reza_Yarahmadi
شنبه 21 اسفند 1389, 17:49 عصر
3.5 مگ هستش؛اشكال نداره؟؟
با نمونه داده هایی که گذاشتید نمیشه فهمید مشکل چیه. قبل از بک آپ گرفتن روی دیتابیس مورد نظرتون راست کلیک کنید و از منوی Tasks گزینه Shrink/Database رو انتخاب کنید و در پنجره باز شده دکمه OK رو بزنید. بعد عملیات بک آپ گیری رو انجام بدید. زمان فشرده سازی هم (در صورتیکه از WinRar استفاده میکنید) از کمبو Compression method رو روی Best بذارید. با این کارها حجمی که میخواید آپلود کنید کم میشه.
بک آپ رو بذارید تا علت مشکل پیدا بشه.

mehrdad_shahian
شنبه 21 اسفند 1389, 17:58 عصر
مرسي،خيلي متشكرم :قلب:

Reza_Yarahmadi
شنبه 21 اسفند 1389, 18:22 عصر
مشکل از Idهای شما بود. کدی که من گذاشتم برای حالتی جواب میده که Idها پشت سرهم و بدون فاصله باشند ولی Idهای شما مرتب نیستند. برای رفعش کد رو بصورت زیر تغییر بدید.
Declare @SumRank bigint, @Rand bigint
Select @SumRank = Sum([Customer_Rank]) From [Customers].[dbo].[IranianBoyCustomer]
Set @Rand = Rand() * @SumRank

;With tbl as(
Select
Row_Number() Over(Order by Customer_Rank) as Id,
*
From
[Customers].[dbo].[IranianBoyCustomer]
),res (Id, [Customer_Rank], Aptness) as(
Select Top 1
Id
,[Customer_Rank]
,Customer_Rank as Aptness
From tbl
UNION ALL
Select
t.Id
,t.Customer_Rank
,t.Customer_Rank + res.Aptness as Aptness
From tbl t, res
Where t.Id = res.Id + 1
)
Select TOP 1 *
From res
Where Aptness> @Rand
Order by Aptness

mehrdad_shahian
شنبه 21 اسفند 1389, 18:41 عصر
من 10 بار اين كد رو اجرا كردم كه از بين اين 10 بار يك بار 80 و2 بار 60 و 3بار 70 رو برگردوند
به نظرتون اين اشكال نداره و من تو برنامم استفادش كنم؟؟؟

يه سوال ديگه:اگه من بخام شرط بزارم بايد چيكار كنم؛مثلا اونايي كه Customer_active مساوي 1(true) هستش

Reza_Yarahmadi
شنبه 21 اسفند 1389, 19:42 عصر
اعداد بصورت تصادفی انتخاب میشه ، ممکنه توی 10 بار تست 3 بار عدد 10 که کمترین احتمال رو داره بیاد. با 10 بار تست نمیشه روی روشهایی که با اعداد تصادفی کار میکنند برداشت درستی داشت باید تعداد تستها رو خیلی بیشتر باشه ، اگر میخواید برداشت بهتری از این روش داشته باشید کد زیر رو تست کنید. این کد 10000بار خروجی بدست میاره و تعداد هر جواب رو نمایش میده.
EXEC SP_EXECUTESQL @Statement = N'
Create Proc TMP
as
Declare @SumRank bigint, @Rand bigint
Select @SumRank = Sum([Customer_Rank]) From [Customers].[dbo].[IranianBoyCustomer]
Set @Rand = Rand() * @SumRank

;With tbl as(
Select
Row_Number() Over(Order by Customer_Rank) as Id,
*
From
[Customers].[dbo].[IranianBoyCustomer]
),res (Id, [Customer_Rank], Aptness) as(
Select Top 1
Id
,[Customer_Rank]
,Customer_Rank as Aptness
From tbl
UNION ALL
Select
t.Id
,t.Customer_Rank
,t.Customer_Rank + res.Aptness as Aptness
From tbl t, res
Where t.Id = res.Id + 1
)
Select TOP 1 *
From res
Where Aptness> @Rand
Order by Aptness'

Create Table #Temp(
Id int,
Rank int,
Aptness int)

Declare @i int
Set @i = 0
While (@i < 10000)
Begin
Insert Into #Temp EXEC TMP
Set @i = @i + 1
End

Select Id, Rank, Count(*) as Count
From #Temp
Group By Id, Rank
Order By Id

Drop Proc TMP
Drop Table #Temp
راستی نیاز نیست با پیام خصوصی اطلاع بدید که سوالتون ادامه داره ، من هروقت بتونم تالار رو چک میکنم.

mehrdad_shahian
شنبه 21 اسفند 1389, 19:46 عصر
مرسي قانع شدم
بابت پيام خصوصي هم عزرخواهي ميكنم.چون يه مقدار كار من عجله اي و خيلي وقته دنبال جواب اين سوال بودم كه شما لطف كردين و زحمت كشدين و به من كمك كردين بازم ميگم متشكرم

يه سوال ديگه:اگه من بخام شرط بزارم بايد چيكار كنم؛مثلا اونايي كه Customer_active مساوي 1(true) هستش رو تو رندم شركت كنن و نشون بده

Reza_Yarahmadi
شنبه 21 اسفند 1389, 22:21 عصر
يه سوال ديگه:اگه من بخام شرط بزارم بايد چيكار كنم؛مثلا اونايي كه Customer_active مساوي 1(true) هستش رو تو رندم شركت كنن و نشون بده
در صورتیکه این شروط روی رکوردهای شرکت کننده در انتخاب تصادفی تاثیر داره (تعیین کننده اینکه چه رکوردهایی در انتخاب شرکت کنند) میتونید توی همون Select اول شرط رو اعمال کنید
;With tbl as(
Select
Row_Number() Over(Order by Customer_Rank) as Id,
*
From
[Customers].[dbo].[IranianBoyCustomer]
Where
YourCondition
)
ولی در صورتیکه بخواید در احتمال انتخاب رکوردها تاثیرشون بدید باید از روشی مثل همون Rank استفاده کنید.

mehrdad_shahian
یک شنبه 22 اسفند 1389, 08:28 صبح
مرسي

شرط اعمال ميشه و لي گاهي وقتا هيچ ركوردي بر نمي گردونه و به نظرم اين موقعه اي اتفاق مي افته كه شرط اعمال ميشه و ركوردي شامل اون شرط دلخواه ميشه.

مثلا من ركورد 8 رو active ش رو false كردم و گفتم اونايي كه active ش true هست رو نشون بده.حالا ركورد 8 رو نشون نميده و لي به نظرم هر موقع كه اونو انتخاب ميكنه جاش خالي ميزاره.كه من نميخام همچين اتفاقي بيفته.
لازمه كه بگم من كلا اين دستور رو دارم براي تبليغات بالاي سايت استفاده ميكنم و تبليغات مشتري ها رو براساس امتياز بالاتر نشون ميده و اوني كه امتيازش بالاتره بيشتر از بقيه.

Reza_Yarahmadi
یک شنبه 22 اسفند 1389, 10:07 صبح
خب دوست من بخاطر اینه که شما شرطتون رو در مجموع Rank گیری دخالت ندادید یعنی مجموع Rank برای همه حساب میشه و در Rand ضرب میشه. کافیه شرط رو در مجموع Rank گیری هم دخالت بدید.
Select @SumRank = Sum([Customer_Rank])
From [Customers].[dbo].[IranianBoyCustomer]
Where YourCondition
(اگر به منطق کد بیشتر دقت کنید به راحتی میتونید خیلی از مشکلاتتون رو حل کنید)

mehrdad_shahian
یک شنبه 22 اسفند 1389, 11:04 صبح
مشكل من حل شد.از اينكه اين مدت ازيتون كردم خيلي عزر ميخام. خيلي خيلي متشكرم