استعلام SQL للحصول على أعلى الدرجات "n" من القائمة

StackOverflow https://stackoverflow.com/questions/37743

  •  09-06-2019
  •  | 
  •  

سؤال

أرغب في العثور على طرق مختلفة لحل مشكلة حياتي الحقيقية التي واجهتني:تخيل أن لديك مسابقة، أو لعبة، يقوم خلالها المستخدمون بجمع النقاط.يجب عليك إنشاء استعلام لإظهار قائمة المستخدمين الحاصلين على أفضل الدرجات "n".

أنا أضرب مثالا للتوضيح.لنفترض أن هذا هو جدول المستخدمين، بالنقاط المكتسبة:

UserId - Points
1      - 100
2      -  75
3      -  50
4      -  50
5      -  50
6      -  25

إذا أردت الحصول على أعلى 3 درجات، ستكون النتيجة:

UserId - Points
1      - 100
2      -  75
3      -  50
4      -  50
5      -  50

يمكن تحقيق ذلك في طريقة عرض أو إجراء مخزن، كما تريد.قاعدة البيانات المستهدفة الخاصة بي هي Sql Server.في الواقع لقد قمت بحل هذه المشكلة، ولكن أعتقد أن هناك طريقة مختلفة للحصول على النتيجة ...أسرع أو أكثر كفاءة من الألغام.

هل كانت مفيدة؟

المحلول

لم يتم اختباره، ولكن يجب أن يعمل:

select * from users where points in
(select distinct top 3 points from users order by points desc)

نصائح أخرى

إليك الحل الذي يعمل - لا أعرف ما إذا كان أكثر كفاءة، وهو SQL Server 2005+

with scores as (
    select 1 userid, 100 points
    union select 2, 75
    union select 3, 50
    union select 4, 50
    union select 5, 50
    union select 6, 25
),
results as (
    select userid, points, RANK() over (order by points desc) as ranking 
    from scores
)
select userid, points, ranking
from results
where ranking <= 3

من الواضح أن أول "مع" هو إعداد القيم، بحيث يمكنك اختبار الثاني مع، والعمل النهائي المحدد - يمكنك البدء بـ "مع النتائج كـ..." إذا كنت تستعلم مقابل جدول موجود.

ماذا عن:

select top 3 with ties points 
from scores
order by points desc

لست متأكدًا مما إذا كانت "مع الروابط" تعمل على أي شيء آخر في SQL Server.

في SQL Server 2005 والإصدارات الأحدث، يمكنك تمرير الرقم "العلوي" كمعلمة int:

select top (@n) with ties points 
from scores
order by points desc

في الواقع، سيكون التعديل على WHERE IN، واستخدام INNER JOIN أسرع بكثير.

SELECT 
   userid, points 
FROM users u
INNER JOIN 
(
   SELECT DISTINCT TOP N 
      points 
   FROM users 
   ORDER BY points DESC
) AS p ON p.points = u.points

bosnic، لا أعتقد أن ذلك سيعمل على النحو المطلوب، فأنا لست على دراية بـ MS SQL ولكني أتوقع أن يُرجع 3 صفوف فقط، ويتجاهل حقيقة أن 3 مستخدمين مرتبطون بالمركز الثالث.

شيء من هذا القبيل يجب أن تعمل:

select userid, points 
   from scores 
   where points in (select top 3 points 
                       from scores 
                       order by points desc) 
   order by points desc

@ روب #37760:

select top N points from users order by points desc

سيحدد هذا الاستعلام 3 صفوف فقط إذا كان N هو 3، راجع السؤال.يجب أن يُرجع "أعلى 3" 5 صفوف.

@Espo شكرًا لك على التحقق من الواقع - تمت إضافة التحديد الفرعي لتصحيح ذلك.

أعتقد أن أسهل رد هو:

select userid, points from users
where points in (select distinct top N points from users order by points desc) 

إذا كنت تريد وضع ذلك في عملية مخزنة تأخذ N كمعلمة، فسيتعين عليك إما قراءة SQL في متغير ثم تنفيذها، أو القيام بخدعة حساب الصفوف:

declare @SQL nvarchar(2000)
set @SQL = "select userID, points from users "
set @SQL = @SQL + " where points in (select distinct top " + @N
set @SQL = @SQL + " points from users order by points desc)"

execute @SQL

أو

SELECT  UserID, Points
FROM     (SELECT  ROW_NUMBER() OVER (ORDER BY points DESC)
         AS Row, UserID, Points FROM Users)
        AS usersWithPoints
WHERE  Row between 0 and @N

يفترض كلا المثالين SQL Server ولم يتم اختبارهما.

@ مات هاميلتون

تعمل إجابتك مع المثال أعلاه ولكنها لن تعمل إذا كانت مجموعة البيانات 100، 75، 75، 50، 50 (حيث ستعرض 3 صفوف فقط).الجزء العلوي مع ربطات العنق يتضمن فقط ربطات العنق الموجودة في الصف الأخير الذي تم إرجاعه...

حصلت عليها Crucible (بافتراض أن SQL 2005 هو خيار).

مرحبًا ، لقد وجدت جميع الإجابات الأخرى طويلة وغير فعالة أن إجابتي ستكون:

select * from users order by points desc limit 0,5

وهذا سيجعل أعلى 5 نقاط

جرب هذا

select top N points from users order by points desc
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top