PDA

View Full Version : سئوال: نحوه sort یک جدول در sql



tolid123456789
شنبه 19 اردیبهشت 1394, 15:17 عصر
سلام
من جدولی به شکل زیر دارم:

جدول1


ردیف
حجم ایجاد شده
تعداد قطعه 1
تعداد قطعه 2
تعداد قطعه 3


1
520
2
5
3


2
1020
3
6
7


3
100
1
9
2


4
200
9
2
1





حالا می خوام جدول بالا (جدول1)رو با شروط زیر sort کنم.
ابتدا بر حسب بیشترین حجم تولید شده جدول رو مرتب کنه و بزرگتریم حجم ایجاد شده رو در در بالاترین رکورد نشون بده. سپس بر اساس تعداد قطعه1 از بیشتر به کمتر sort کنه و بعد بر اساس تعداد قطعه 2 و بعد تعداد قطعه 3.
به عبارتی جدول خروجی به شکل زیر بشه:

جدول2


ردیف
حجم ایجاد شده
تعداد قطعه 1
تعداد قطعه 2
تعداد قطعه 3


2

1020

3
6
7


4
200
9

2
1


3
100
1
9

2


1
520

2

5

3



اگر من sort اول رو روی حجم ایجاد شده قرار بدم و بعد sort های دیگه رو روی تعداد قطعه 1 بعد از اون تعداد قطعه 2 و سپس تعداد قطعه 3، ابتدا جدول بر حسب ستون حجم ایجاد شده مرتب میشه و بعد بقیه آیتم های sort اعمال می شند و جدول ایجاد شده به شکل زیر (جدول 3) در می یاد.


جدول3


ردیف

حجم ایجاد شده

تعداد قطعه 1

تعداد قطعه 2

تعداد قطعه 3



2

1020

3

6

7



1

520

2

5

3



4

200

9

2

1



3

100

1

9

2



در صورتیکه من می خوام خروجیم شبیه جدول 2 بشه.
لطفا راهنمایی کنید.


ممنون

tooraj_azizi_1035
شنبه 19 اردیبهشت 1394, 16:01 عصر
سلام
با این فرض که جدول 4 ردیف دارد:

select * from t
where c1=(select MAX(c1) from t)

union

select * from t
where c2=(select MAX(c2) from t)

union

select * from t
where c3=(select MAX(c3) from t)

union

select * from t
where c4=(select MAX(c4) from t)





نکته ای که وجود داره اینه که اگه یک رکورد همه مقادیر max رو داشته باشه چهار بار تکرار میشه که با union حذف میشه و باید مطمئن بشیم که رکوردهایی که تو خروجی نیومدن هم باید در خروجی ظاهر بشن:

with cte (id ,c1, c2, c3, c4)
as
(
select * from t
where c1=(select MAX(c1) from t)

union

select * from t
where c2=(select MAX(c2) from t)

union

select * from t
where c3=(select MAX(c3) from t)

union

select * from t
where c4=(select MAX(c4) from t)


)

select * from cte
union
select * from t
where id not in (select id from cte)

tolid123456789
شنبه 19 اردیبهشت 1394, 16:11 عصر
ممنون از جوابتون
مشکل اینجاست که جدول کاملا داینامیکه و هر بار که عملیات انجام میشه تعداد رکوزد ها تغییر میکنه از یک تا بینهایت.

tolid123456789
شنبه 19 اردیبهشت 1394, 16:21 عصر
مثلا وقتی صد تا رکورد داریم ابتدا 4 رکورد اول با توجه به متن سئوال مرتب میشند، ترتیب بقیه رکورها اهمیت نداره.

SabaSabouhi
شنبه 19 اردیبهشت 1394, 20:27 عصر
سلام
می‌تونم بپرسم یه همچنین ترتیبی به چه دردی می‌خوره؟
راستش من فکر می‌‌کنم بعضی وقت‌ها بجای پاسخ به یه سوال باید سوال اصلی رو پیدا کرد و به اون جواب داد.

و دیگه این که اگه به قول شما، یک‌صد سطر داشته باشیم، انتطار هست که فقط سه سطر اول با اون فرمول نمایش
داده بشه؟ یا بقیه سطرها هم باید نمایش داده بشه؟
اگه جواب مثبت هست، بقیه‌ی سطرها با چه ترتیبی نمایش داده بشن؟

برای این پرسش راه حل خاصی در نظرم هست، اما برای پاسخ قطعی نیاز به پاسخ به پرسش‌های بالا دارم.

اما به صورت خلاصه بگم که شما می‌تونی با نوشتن یک تابع، یه ستون مجازی تولید کنی که حاوی عددی هست که
اولین Order by رو به اون می‌دی. برای سطری که بزرگ‌ترین حجم رو داره، عدد 1 رو برگردونه، برای سطری که تعداد قطعه‌ی 1
رو داره عدد 2 و به همین ترتیب برای اون‌هایی که اهمیت دارن به ترتیب مقدایر 3 و 4و . . .
و برای باقی‌مانده‌ی سطرها عدد 99 رو بر گردونه.

صبا صبوحی

tolid123456789
یک شنبه 20 اردیبهشت 1394, 08:48 صبح
سلام
من یک دستگاه برش لوله دارم. در این دستگاه ما می تونیم 3 سایز مختلف تولید کنیم. طول هر لوله ای که ما برش می زنیم متغیره. مثلا من در برش اول یک لوله 12000 میلیمتری دارم. قطعه 1 طولش 1020، قطعه 2 مثلا 1050 و قطعه 3 مثلا 1180 میلیمتر هست. حالا تعداد تمام حالت های برش رو نرم افزار در یک جدول به من نشون میده. فرض کنید این حالت ها همون جدول شماره 1 در سئوال اول این تاپیک باشه.
اپراتور من در حال حاضر به صورت چشمی بین گزینه های ایجاد شده، همه رو نگاه می کنه و یکی رو انتخاب و گزینه برش رو می زنه.
تا اینجا مشکلی نیست و سیستم در حال کارکردنه.
برای برش اولویت های زیر وجود داره.
1- اون برشی (رکوردی) که بیشترین حجم رو تولید میکنه (هر قطعه بر اساس سایزش یک حجمی رو تولید میکنه) در سطر اول باشه
2- قطعه 1 مهمترین قطعه ماست، و ما می خوایم در رکورد دوم بیشترین مقدار تولید شده از این قطعه نمایش داده بشه
3-مانند بند 2 قطعه 2 و 3 اولویت های ماست و باید در رکوردهای سوم و چهارم بیشترین مقدیر اونها نمایش داده بشه.
4-نحوه قرارگیری بقیه رکوردها اهمیتی نداره.

بنده جدولی می خوام که بتونه ترتیب قرارگیری رکوردها رو با اولویت های بالا نمایش بده و بقیه رکوردها رو هم بعد از این 4 رکورد نمایش بده. چون در حالت هایی امکان داره مدیریت دستور بده رکوردی به غیر از این چهار رکورد اول انتخاب بشه.

ممنون از جوابتون

tooraj_azizi_1035
یک شنبه 20 اردیبهشت 1394, 10:39 صبح
cte نوشته شده میاد 4 رکورد اول رو تولید میکنه البته گفتم ممکنه یک رکورد بخصوص دارای چهار مقدار ماکزیمم در 4 ستون رو داشته باشه پس می تونه 4 بار تکرار بشه که با union حذف میشه و فقط یکبار ظاهر میشه کوئری زیر رو هم آخر سر به انتهای جواب اضافه می کنیم تا بقیه رکوردها هم زیر جواب فعلی قرار بدیم.



select * from t
where id not in (select id from cte)

tolid123456789
یک شنبه 20 اردیبهشت 1394, 11:06 صبح
سلام
درباره کد پاسخ شماره 2 شما اولین کد رو امتحان کردم (با فرض داشتن داده های جدول1 در اولین ارسال این صفحه) جواب به شکل زیر شد:
131064

کد قسمت دوم شما رو هم تست کردم خروجی به شکل زیر شد:
131065
خروجی مورد نیاز من با این فرق میکنه.

SabaSabouhi
یک شنبه 20 اردیبهشت 1394, 12:13 عصر
سلام
من یک دستگاه برش لوله دارم. در این دستگاه ما می تونیم 3 سایز مختلف تولید کنیم. طول هر لوله ای که ما برش می زنیم متغیره. مثلا من در برش اول یک لوله 12000 میلیمتری دارم. قطعه 1 طولش 1020، قطعه 2 مثلا 1050 و قطعه 3 مثلا 1180 میلیمتر هست. حالا تعداد تمام حالت های برش رو نرم افزار در یک جدول به من نشون میده. فرض کنید این حالت ها همون جدول شماره 1 در سئوال اول این تاپیک باشه.
اپراتور من در حال حاضر به صورت چشمی بین گزینه های ایجاد شده، همه رو نگاه می کنه و یکی رو انتخاب و گزینه برش رو می زنه.
تا اینجا مشکلی نیست و سیستم در حال کارکردنه.
برای برش اولویت های زیر وجود داره.
1- اون برشی (رکوردی) که بیشترین حجم رو تولید میکنه (هر قطعه بر اساس سایزش یک حجمی رو تولید میکنه) در سطر اول باشه
2- قطعه 1 مهمترین قطعه ماست، و ما می خوایم در رکورد دوم بیشترین مقدار تولید شده از این قطعه نمایش داده بشه
3-مانند بند 2 قطعه 2 و 3 اولویت های ماست و باید در رکوردهای سوم و چهارم بیشترین مقدیر اونها نمایش داده بشه.
4-نحوه قرارگیری بقیه رکوردها اهمیتی نداره.

بنده جدولی می خوام که بتونه ترتیب قرارگیری رکوردها رو با اولویت های بالا نمایش بده و بقیه رکوردها رو هم بعد از این 4 رکورد نمایش بده. چون در حالت هایی امکان داره مدیریت دستور بده رکوردی به غیر از این چهار رکورد اول انتخاب بشه.

ممنون از جوابتون

سلام
خوب پس پیش‌نهاد می‌کنم همون نظر من رو انجام بدی. یه Function بنویس که ستون ترتیب رو برات ایجاد کنه. این شکلی دستت باز هست
که هر نوع ترتیبی رو اعمال کنی.
مثلاً

CREATE Function dbo.MyOrder ( int @RowId )
RETURNS int
AS
BEGIN
DECLARE @Id as Integer


SELECT Top 1 @Id = Id
FROM MyTable
ORDER BY FirstColumn DESC
IF ( @RowId = @Id )
RETURN 1


SELECT Top 1 @Id = Id
FROM MyTable
ORDER BY SecondColumn DESC
IF ( @RowId = @Id )

RETURN 2

SELECT Top 1 @Id = Id
FROM MyTable
ORDER BY ThirdColumn DESC
IF ( @RowId = @Id )

RETURN 3

RETURN 99

END

به‌جای MyTable, FirstColumn, SecondColumn, ThirdColumn مقادیر مناسب رو قرار بده
و برای گرفتن خروجی به این شکل عمل کن:


SELECT *, dbo.MyOrder( Id)
FROM MyTable
ORDER BY dbo.MyOrder( Id )


به همین سادگی می‌تونی هر نوع ترتیبی که خواستی رو ایجاد کنی.
البته این روش ممکنه تو حجم بالای دیتا کمی کند بشه. اما اگه تعداد سطرها زیاد نباشه اصلاً قابل ملاحظه نیست.

صبا صبوحی

tooraj_azizi_1035
یک شنبه 20 اردیبهشت 1394, 12:19 عصر
You can't refuse:





with cte1 (id ,c1, c2, c3, c4, rownum)
as
(
select top 1 *, 1 as rownum from #t
where c1=(select MAX(c1) from #t)

union all

select top 1 *, 2 as rownum from #t
where c2=(select MAX(c2) from #t)

union all

select top 1 *, 3 as rownum from #t
where c3=(select MAX(c3) from #t)

union all

select top 1 *, 4 as rownum from #t
where c4=(select MAX(c4) from #t)


),
cte2(id ,c1, c2, c3, c4)
as(
select distinct id ,c1, c2, c3, c4 from cte1)
,
cte3(id ,c1, c2, c3, c4, rownum)
as(
select *, ROW_NUMBER() over (order by id) rownum from cte2 )
,
cte4(id ,c1, c2, c3, c4)
as(
select top 100 percent cte1.id, cte1.c1, cte1.c2, cte1.c3, cte1.c4 from cte1
join cte3 on cte1.rownum=cte3.rownum
order by cte1.rownum
)
select * from cte4
union all
select * from #t
where id not in (select id from cte4)

tolid123456789
یک شنبه 20 اردیبهشت 1394, 14:17 عصر
You can't refuse:







with cte1 (id ,c1, c2, c3, c4, rownum)
as
(
select top 1 *, 1 as rownum from #t
where c1=(select MAX(c1) from #t)

union all

select top 1 *, 2 as rownum from #t
where c2=(select MAX(c2) from #t)

union all

select top 1 *, 3 as rownum from #t
where c3=(select MAX(c3) from #t)

union all

select top 1 *, 4 as rownum from #t
where c4=(select MAX(c4) from #t)


),
cte2(id ,c1, c2, c3, c4)
as(
select distinct id ,c1, c2, c3, c4 from cte1)
,
cte3(id ,c1, c2, c3, c4, rownum)
as(
select *, ROW_NUMBER() over (order by id) rownum from cte2 )
,
cte4(id ,c1, c2, c3, c4)
as(
select top 100 percent cte1.id, cte1.c1, cte1.c2, cte1.c3, cte1.c4 from cte1
join cte3 on cte1.rownum=cte3.rownum
order by cte1.rownum
)
select * from cte4
union all
select * from #t
(where id not in (select id from cte4)








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