سؤال

لقد تم استخدام GROUP BY لجميع أنواع الاستعلامات المجمعة على مر السنين.لقد قمت مؤخرًا بإجراء هندسة عكسية لبعض التعليمات البرمجية التي تستخدم PARTITION BY لأداء التجميعات.في قراءة جميع الوثائق التي يمكنني العثور عليها PARTITION BY, ، يبدو الأمر مشابهًا كثيرًا GROUP BY, ، ربما مع إضافة القليل من الوظائف الإضافية؟هل هما نسختان من نفس الوظيفة العامة أم أنهما مختلفان تمامًا؟

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

المحلول

يتم استخدامها في أماكن مختلفة. group by يعدل الاستعلام بأكمله، مثل:

select customerId, count(*) as orderCount
from Orders
group by customerId

ولكن partition by فقط يعمل على وظيفة نافذة, ، مثل row_number:

select row_number() over (partition by customerId order by orderId)
    as OrderNumberForThisCustomer
from Orders

أ group by عادة يقلل عادة من عدد الصفوف التي تم إرجاعها عن طريق تدحرجها وحساب المتوسطات أو المبالغ لكل صف. partition by لا يؤثر على عدد الصفوف التي تم إرجاعها، لكنها تغير كيفية حساب نتيجة وظيفة النافذة.

نصائح أخرى

يمكننا أن نأخذ مثال بسيط.

النظر في جدول اسمه TableA مع القيم التالية:

id  firstname                   lastname                    Mark
-------------------------------------------------------------------
1   arun                        prasanth                    40
2   ann                         antony                      45
3   sruthy                      abc                         41
6   new                         abc                         47
1   arun                        prasanth                    45
1   arun                        prasanth                    49
2   ann                         antony                      49

GROUP BY

يمكن استخدام مجموعة SQL By Clause في عبارة مختارة لجمع البيانات عبر سجلات متعددة ومجموعة النتائج حسب واحد أو أكثر من الأعمدة.

في مجموعة كلمات أكثر بسيطة يتم استخدام المجموعة حسب العبارة بالاقتران مع الوظائف الإجمالية لتجميع النتيجة حسب أعمدة واحدة أو أكثر.

بناء الجملة:

SELECT expression1, expression2, ... expression_n, 
       aggregate_function (aggregate_expression)
FROM tables
WHERE conditions
GROUP BY expression1, expression2, ... expression_n;

يمكننا التقدم بطلب GROUP BY في طاولتنا:

select SUM(Mark)marksum,firstname from TableA
group by id,firstName

نتائج:

marksum  firstname
----------------
94      ann                      
134     arun                     
47      new                      
41      sruthy   

في طاولتنا الحقيقية لدينا 7 صفوف وعندما نطبق GROUP BY id, ، مجموعة الخادم النتائج بناء على id:

بكلمات بسيطة:

هنا GROUP BY يقلل عادة عدد الصفوف التي عادت عن طريق تدحرجها وحسابها Sum() لكل صف.

PARTITION BY

قبل الذهاب إلى التقسيم، دعونا ننظر إلى OVER بند:

وفقا لتعريف MSDN:

يحدد Over Overluse نافذة أو مجموعة من الصفوف المحددة من المستخدمين ضمن مجموعة نتيجة للاستعلام. وظيفة النافذة ثم يحسب قيمة لكل صف في النافذة. يمكنك استخدام جملة أكبر مع وظائف لحساب القيم المجمعة مثل المتوسطات المتحركة، والمجاميع التراكمية، أو مجاميع التشغيل، أو أعلى ن لكل مجموعة من النتائج.

التقسيم من قبل لن يقلل من عدد الصفوف التي عادت.

يمكننا تطبيق التقسيم من خلال جدول مثالنا:

SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA

نتيجة:

marksum firstname 
-------------------
134     arun                     
134     arun                     
134     arun                     
94      ann                      
94      ann                      
41      sruthy                   
47      new  

انظر إلى النتائج - سوف تقسم الصفوف والعودة الكل الصفوف، على عكس المجموعة.

partition by لا تنشأ بالفعل البيانات. يسمح لك بإعادة تعيين شيء ما على أساس لكل مجموعة. على سبيل المثال، يمكنك الحصول على عمود ترتيبي داخل مجموعة من خلال التقسيم على حقل المجموعة واستخدام rownum() على الصفوف داخل تلك المجموعة. يمنحك هذا شيئا يتصرف قليلا مثل عمود الهوية الذي يعيد تعيينه في بداية كل مجموعة.

التقسيم عن طريق تقسيم النتيجة المحددة في أقسام. يتم تطبيق وظيفة النافذة على كل قسم إعادة تشغيل الحساب بشكل منفصل وحسابات لكل قسم.

وجدت في هذا الرابط: فوق جملة

يوفر بيانات ملفوفة دون المتداول

أي أفترض أنني أريد إرجاع الموضع النسبي لمنطقة المبيعات

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

هذا يعني أنه سيكون لديك بيانات متكررة، ولكن قد يناسب المستهلك النهائي بمعنى أن البيانات قد تم تجميع البيانات ولكن لم يتم فقد البيانات - كما سيكون الحال مع المجموعة.

PARTITION BY هو تحليلي، في حين GROUP BY هو التجمع. لكي تستخدم PARTITION BY, ، عليك أن تحتوي على ذلك مع فوق جملة.

اعتبارا من قسم فهمي هو متطابق تقريبا للمجموعة من قبل، ولكن مع الاختلافات التالية:

هذه المجموعة من خلال المجموعات التي تقوم بها بالفعل النتيجة المحددة التي تعود إلى صف واحد لكل مجموعة، مما يؤدي لذلك في SQL Server يسمح فقط في الوظائف أو الأعمدة الإجمالية القائمة فقط التي تعد جزءا من المجموعة بواسطة جملة (في أي حالة خادم SQL يمكن أن تضمن أن هناك فريدة من نوعها النتائج لكل مجموعة).

فكر في مثال MySQL الذي يسمح له في أعمدة قائمة تحديد الأعمدة غير المحددة في جملة المجموعة حسب جملة، وفي هذه الحالة لا يزال يتم إرجاع صف واحد لكل مجموعة، ولكن إذا كان العمود ليس لديه نتائج فريدة، فلا يوجد ضمان ماذا سيكون الإخراج!

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

كملخص، ستكون المجموعة من خلال الأفضل عند الاحتياجات من إخراج صف واحد لكل مجموعة، والتقسيم سيكون أفضل عندما يحتاج المرء إلى جميع الصفوف ولكن لا يزال يريد الوظيفة الإجمالية بناء على مجموعة.

بالطبع قد يكون هناك أيضا مشاكل الأداء، انظر http://social.msdn.microsoft.com/forums/ms-my/transactsql/thread/b20c2b5-1607-40bc-b7a7-0C60A2A55FBA..

لنفترض أن لدينا 14 سجلات name عمود في الجدول

في group by

select name,count(*) as totalcount from person where name='Please fill out' group BY name;

سيعطي العد في صف واحد IE 14

ولكن في partition by

select row_number() over (partition by name) as total from person where name = 'Please fill out';

سوف 14 صفوف من الزيادة في عدد

ملاحظة صغيرة.آلية التشغيل الآلي لإنشاء SQL ديناميكيًا باستخدام "التقسيم حسب"، يكون تنفيذها أسهل بكثير فيما يتعلق بـ "المجموعة حسب".في حالة "التجميع حسب"، يجب أن نهتم بمحتوى عمود "التحديد".

اسف للغتى الانجليزيه.

لديها سيناريوهات الاستخدام المختلفة حقا. عند استخدام المجموعة من خلال دمج بعض السجلات للأعمدة التي هي نفسها وتجميع مجموعة النتائج.

ومع ذلك، عند استخدام التقسيم حسب مجموعة النتائج الخاصة بك هو نفسه، فإن لديك تجميع فقط على وظائف النافذة ولا دمج السجلات، فستظل لها نفس العدد من السجلات.

فيما يلي مقال مسدود مفيد يشرح الفرق:http://alevryustemov.com/sql/sql-partition-by/

-- BELOW IS A SAMPLE WHICH OUTLINES THE SIMPLE DIFFERENCES
-- READ IT AND THEN EXECUTE IT
-- THERE ARE THREE ROWS OF EACH COLOR INSERTED INTO THE TABLE
-- CREATE A database called testDB


-- use testDB
USE [TestDB]
GO


-- create Paints table
CREATE TABLE [dbo].[Paints](
    [Color] [varchar](50) NULL,
    [glossLevel] [varchar](50) NULL
) ON [PRIMARY]

GO


-- Populate Table
insert into paints (color, glossLevel)
select 'red', 'eggshell'
union
select 'red', 'glossy'
union
select 'red', 'flat'
union
select 'blue', 'eggshell'
union
select 'blue', 'glossy'
union
select 'blue', 'flat'
union
select 'orange', 'glossy'
union
select 'orange', 'flat'
union
select 'orange', 'eggshell'
union
select 'green', 'eggshell'
union
select 'green', 'glossy'
union
select 'green', 'flat'
union
select 'black', 'eggshell'
union
select 'black', 'glossy'
union
select 'black', 'flat'
union
select 'purple', 'eggshell'
union
select 'purple', 'glossy'
union
select 'purple', 'flat'
union
select 'salmon', 'eggshell'
union
select 'salmon', 'glossy'
union
select 'salmon', 'flat'


/*   COMPARE 'GROUP BY' color to 'OVER (PARTITION BY Color)'  */

-- GROUP BY Color 
-- row quantity defined by group by
-- aggregate (count(*)) defined by group by
select count(*) from paints
group by color

-- OVER (PARTITION BY... Color 
-- row quantity defined by main query
-- aggregate defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color)
from paints

/* COMPARE 'GROUP BY' color, glossLevel to 'OVER (PARTITION BY Color, GlossLevel)'  */

-- GROUP BY Color, GlossLevel
-- row quantity defined by GROUP BY
-- aggregate (count(*)) defined by GROUP BY
select count(*) from paints
group by color, glossLevel



-- Partition by Color, GlossLevel
-- row quantity defined by main query
-- aggregate (count(*)) defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color, glossLevel)
from paints
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top