English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

جملة SQL للجمع المجموعي بعد التجميع واجمع المجموع الكلي (بإجراء بعض الترتيب)

اليوم رأيت هذا المقال وشعرت بأنه يحتوي على الكثير من المعلومات، ولكنه كان مرتبًا بشكل سيء، لا يمكن تنظيمه بشكل جيد، لذا قام محرر دليل التصفية بتنظيمه ببساطة، آمل أن تكونوا راضين عن القراءة

جملة SQL لمجموع المجموعات بعد التجميع وال总计
 
1) تريد الحصول على مجموع المجموعات وال总计 دفعة واحدة، SQL:

SELECT حقل التجميع FROM الجدول
GROUP BY حقل التجميع
احسب مجموع (COUNT(*))

2) مجموع المجموعات 1:

SELECT COUNT(*)
FROM (SELECT حقل التجميع FROM الجدول
GROUP BY حقل التجميع
) بديل

 
3) مجموع المجموعات 2:

SELECT COUNT(*)
FROM (SELECT distinct حقل التجميع FROM الجدول) بديل

4) احصاء عدد الأنواع بعد التجميع:
 
مثال1: مجموع المجموعات

SELECT JSSKQK_JGH FROM SJ_JSSKQK WHERE JSSKQK_JGH IN (SELECT JSJBXX_JGH FROM SJ_JSJBXX WHERE JSJBXX_JSLXM1=1) GROUP BY JSSKQK_JGH HAVING ((SUM(JSSKQK_SSKCXS1) /40)>5) 

上面的语句已经可以满足要求分组了.假设执行后有3条记录,怎么才能把这个COUNT值求出?

select count(*) from
(
 SELECT JSSKQK_JGH 
 FROM SJ_JSSKQK 
 WHERE JSSKQK_JGH IN (SELECT JSJBXX_JGH FROM SJ_JSJBXX WHERE JSJBXX_JSLXM1=1) 
 GROUP BY JSSKQK_JGH HAVING ((SUM(JSSKQK_SSKCXS1) /40)>5) 
) t

مثال 2: [PL/SQL] كيفية الحصول على سجلات التاريخ الأكبر في كل مجموعة بعد التجميع

TABLE: A
A                  B                                                  C                  D
1                  2001/01/01                                                                          1                  1
1                  2001/12/12                                                                          2                  2
3                  2002/01/01                                                                          3                  3
3                  2003/12/12                                                                                  4                  4

بالنسبة للعنصر A،كيف يمكنني الحصول على البيانات الأكبر في كل مجموعة؟

1                  2001/12/12                                                                          2                  2
3                  2003/12/12                                                                                  4                  4

طريقتي الغبية:

SELECT *
FROM A
WHERE (A,B) IN(
SELECT A,MAX(B)
FROM A
GROUP BY A
)

هل هناك طريقة أفضل؟

1،select * from a out
where b = (select max(b) from a in
                         where in.a = out.a)

2،Select * from
(select a, row_number() over (partition by a
order by b desc) rn
from a)
where rn=1

3،Select a, b,c,d from
(select a, b,c,d,row_number() over (partition by a
order by b desc) rn
from a)
where rn=1

4،select A,B,C,D from test

  where rowid in
  (
     select rd from
     (
     select rowid rd ,rank() over(partition A order by B desc)rk from test
     where rk=1
    
    
  )
  )

مثال 3: روشی برای دریافت اولین داده در هر گروه با استفاده از عبارت گروه‌بندی SQL
از بانک اطلاعاتی Northwind استفاده کنید

ابتدا جدول Employees را جستجو کنید

نتایج جستجو:

در ستون city فقط 5 شهر وجود دارد

از ROW_NUMBER() OVER(PARTITION BY COL1 ORDER BY COL2) برای گروه‌بندی استفاده می‌شود. توجه: بر اساس COL1 گروه‌بندی می‌شود، در داخل هر گروه بر اساس COL2 مرتب می‌شود و این تابع مقدار محاسبه شده را نشان می‌دهد که نشان‌دهنده شماره ترتیب مرتب شده در هر گروه است (مقدار منحصر به فرد پیاپی در داخل هر گروه).

عبارت sql به صورت زیر است:

select EmployeeID,LastName,FirstName,Title,TitleOfCourtesy,City,ROW_NUMBER() over(partition by City order by EmployeeID) as new_index
from Employees

تصویر نتیجه اجرا:

می‌توان دید که بر اساس City گروه‌بندی شده و EmployeeID مرتب شده است.

انتخاب اولین رکورد در گروه

عبارت اجرایی:

select * from
(select EmployeeID,LastName,FirstName,Title,TitleOfCourtesy,City,ROW_NUMBER() over(partition by City order by EmployeeID) as new_index
from Employees) a where a.new_index=1

تصویر نتیجه اجرا:

مثال 4: چگونه در نتایج گروه‌بندی شده SQL، اولین رکورد هر گروه را دریافت کنیم
Eric   red   20
eric   blue  30
andy red   10
andy  blue  5

مثال، فقط دریافت دسته‌های سیاه.

1،declare @fTable table (fName varchar(10), fColor varchar(10), fOrder int)
 
insert into @fTable values('Eric', 'red', 20)
insert into @fTable values('eric', 'blue', 30)
insert into @fTable values('andy', 'red', 10)
insert into @fTable values('andy', 'blue', 5)
 
-- فقط دریافت قرمز
select * from @fTable where fColor = 'red'
-- 每个 fColor 取一条记录(按 fOrder 正序)
select * from @fTable A where fName = (select top 1 fName from @fTable where fColor = A.fColor order by fOrder )
-- 每个 fColor 取一条记录(按 fOrder 反序)
select * from @fTable A where fName = (select top 1 fName from @fTable where fColor = A.fColor order by fOrder desc)
 
2،SQL2005以上版本
select * from (select *,row=row_number()over(partition by Color order by Color) from table1)t where row=1 and color='xx'--加上條件

SQL2000用 top 1

例子5:一条SQL语句搞定分组并且每组限定记录集的数量
 
如果我想得到这样一个结果集:分组,并且每组限定记录集的数量,用一条SQL语句能办到吗?

比如说,我想找出学生期末考试中,每科的前3名,只用一条SQL语句,该怎么写?

表[TScore]的结构

code      学号 char
subject  科目 int
score     成绩 int

可以这样写:

    SELECT [code]
        ,[subject]
        ,[score]
    FROM (
        SELECT *
        ,RANK() OVER(PARTITION BY subject ORDER BY score DESC) AS Row
        FROM TScore
    ) AS a
    WHERE Row <= 3 ;

例子6:SQL获取每个分组的第一条记录

SQL查询以下伪数据获取粗体字行的记录
ID,Name,ItemID,Price,CreatedOn
1 a 1 10.00 xxx1
2 a 1 12.00 xxx2
3 b 1 9.00 xxx1
4 b 1 11.50 xxx2
5 c 1 20.00 xxx1
6 a 2 21.00 xxx1
7 a 2 23.00 xxx2
8 b 2 35.00 xxx1
9 c 2 31.00 xxx1
10 c 2 30.50 xxx2
 
获取每个分组中的第一条记录,当ItemID有多条记录时,选取Price最高的
 
--sql2000
select *
from tbname k
where not exists(select * from tbname where
 name=k.name and ITemID=K.ITemID and k.price<price
)
--sql2005
select ID,Name,ItemID,Price,CreatedOnfrom (select *,rn=ROW_NUMBER()over(PARTITION by name,ITemID order by price desc) from tb ) kwhere k.rn=1

例子7:分组后取第一条记录的SQL语句
分享

有如下表结构:  
  字段.................A,.................B,.................C  
  值为.................a1,.................b1,.................c1  
            a2,.................b2,.................c2  
            a2,.................b3,.................c3  
            a3,.................b4,.................c4  
            a3,.................b5,.................c5  

想要得到的结果集以A字段为分组条件,并取出每一个分组中的第一条记录,如下:  
            A,.................B,.................C  
  值为.................a1,.................b1,.................c1.................--a1分组的第一条记录。  
            a2,.................b2,.................c2.................--a2分组的第一条记录。  
            a3,.................b4,.................c4.................--a3分组的第一条记录。

select......*......from......表......tem......where......c=(select......top......1......c......from......表......where......a=tem.a)

现有数据表call如下:  
   
  zj.................th.................bj  
  -------------......--------......-------------  
  03106666666 00001 03101111111  
  13711111111 00001 031122222222  
  03108898888 950000  
  031177778777 950000  
  031155955555 00001 031187888876  
   
  Note: If th is 950000, then bj is empty, and if th is 00001, then bj is not empty.  
   
  1、bj grouping  
  select substr(bj,1,4) as 区号,count(*) as 呼叫总量 from call  
  group by substr(bj,1,4);  
  Execution result  
   
  区号                                                                                         呼叫总量  
  ------------                 --------------  
  0310                                                                                         1  
  0311                                                                                         2  
                                    2              
   
  2、zj grouping, the condition is the record where th is 950000  
  select substr(zj,1,4) as 区号,count(*) as 呼叫总量 from call  
  where th=950000  
  group by substr(zj,1,4);  
  Execution result:  
   
  区号                                                                                         呼叫总量  
  ------------                 --------------  
  0310                                                                                         1  
  0311                                                                                         1  
   
  Can there be a statement that can achieve the following result:  
   
  区号                                                                                         呼叫总量  
  ------------                 --------------  
  0310                                                                                         2  
  0311                                                                                                 3  
   
  Note: To get the result, add the row corresponding to 1 and the row corresponding to 2.

union together and sum  
  select 区号,sum(呼叫总量) from    
  (select substr(bj,1,4) as 区号,count(*) as 呼叫总量 from call  
  group by substr(bj,1,4))  
  union all  
  (select substr(zj,1,4) as 区号,count(*) as 呼叫总量 from call  
  where th=950000  
  group by substr(zj,1,4))  
  group by 区号;

هذا يجب أن يعمل في Oracle.

select    
          decode(th,'950000',substr(zj,1,4),substr(bj,1,4)) as 区号,  
          count(*) as呼叫总量    
من    
          call  
group by  
          decode(th'950000',substr(zj,1,4),substr(bj,1,4))

decode(الشرط,قيمة 1,القيمة المترجمة 1,قيمة 2,القيمة المترجمة 2,...قيمة n,القيمة المترجمة n,القيمة الافتراضية)

معنى هذا الدالة كالتالي:

IF شرط=قيمة 1 THEN
    RETURN(القيمة المترجمة 1)
ELSIF شرط=قيمة 2 THEN
    RETURN(القيمة المترجمة 2)
    ......
ELSIF شرط=قيمة n THEN
    RETURN(القيمة المترجمة n)

ELSE
    RETURN(القيمة الافتراضية)
END IF

 

مثال 8: في SQL Server2005/2008، قم بتجميع السجلات، ووصول إلى النصوص N الأولى في كل مجموعة
افترض أن هناك جدولًا، جملة SQL كالتالي:
  
CREATE TABLE [dbo].[scan](
    [km] [int] NULL,
    [kh] [int] NULL,
    [cj] [int] NULL
على [PRIMARY]

    حيث km هو رمز المادة، kh هو رمز المتقدم، cj هو الدرج، يتم تجميع km وkh، ووصول إلى سجلات النصوص الـ 2 الأولى في كل مجموعة (مرتبة بناءً على cj من الأعلى إلى الأدنى). الفكرة الأساسية هي إضافة سلسلة مرتبة إلى كل مجموعة، ثم استخدام where للحصول على سلسلة أقل من أو تساوي 2. جملة SQL كالتالي:
select * from
(
    select a.km,a.kh,cj,row_number() over(partition by a.km order by a.km,a.cj desc) n
    من
        (select km,kh,SUM(cj) cj from scan group by km,kh) a
) b حيث n<=2 order by km, cj desc

النتيجة النهائية كما في الشكل التالي.

مثال 9: كيف يمكن تنفيذ جملة SQL لتحقيق المجموعات Group وتسجيل النصوص N الأولى
في الجدول A، قم بتجميع المجموعات بناءً على الحقل B وتسجيل الأرقام الأربعة الأولى في كل مجموعة بناءً على الحقل C، واطلب من النتائج أن تحتوي على جميع الحقول، كيف يمكن كتابة جملة SQL؟ على الرغم من أن الجملة SQL التالية يمكن تنفيذها، ولكن بسبب كمية البيانات الكبيرة، يستغرق وقتًا طويلاً، هل هناك طريقة لاستخراج السجلات المجمعة دون استخدام الاتصال بالجدول؟ شكرًا لكثيرًا!
select *
من الجدول A كـ t1
where الرئيسية في(
select top 3 主键
from 表A as t2
where t1.B=t2.B
order by t2.C)

Comment (hidden comment)
Answer 1
Author: Zou Jian

select id=identity(int,1,1),b, 主键 into # from 表A order by B,C

select a.*
from 表A a, # b,(select id1=min(id),id2=min(id)+2 from # group by b)c
where a.主键=b.主键
and b.id between c.id1 and c.id2

drop table #

Answer 2
Author: aierong

How many methods do you have to find the top 2 in each group? (MS SQL2000)

create table abc(
i nvarchar(10),
ii int,
iii int,
iiii int,
price money)
Go
insert into abc
select 'b',1,2,1,11
union all
select 'b',211,2,1,211
union all
select 'a',21,2,1,311
union all
select 'd',41,42,1,411
union all
select 'd',41,42,1,511
union all
select 'd',41,42,1,611
union all
select 'e',1,2,1,11
union all
select 'e',71,2,1,31
union all
select 'e',61,2,1,911
union all
select 'e',771,2,1,1
go

The required result is:
By grouping i, find the top 2 records with the highest price in each group

i ii iii iiii price
---------- ----------- ----------- ----------- ---------------------
a 21 2 1 311.0000
b 1 2 1 11.0000
b 211 2 1 211.0000
d 41 42 1 511.0000
d 41 42 1 611.0000
e 71 2 1 31.0000
e 61 2 1 911.0000

1.
select *
from abc a
where (
select counthttp://dev1.haocang.com:8080/kb/images/icons/emoticons/star_yellow.gif from abc b
where a.i=b.i and b.price>a.price)<2
order by i,price

استعلامات متصلة، تحديد الكمية

2.
select i,ii,iii,iiii,price
from (
select (select isnull(sum(1),0)+1 from abc b where a.i=b.i and a.price<b.price) ids,*
from abc a) tem
where ids<3
order by i,price

إنشاء جدول داخلي، ترتيب كل مجموعة في جدول الداخل tem، وإدخال الرقم التسلسلي في عمود جديد ids

3.
declare @looptime int
declare @count int
declare @i nvarchar(10)
/تعريف متغير الجدول @abc، ويكون نوع كل عمود في جدول ABC متشابهًا/
declare @abc table(
i nvarchar(10),
ii int,
iii int,
iiii int,
price money)
declare @tem table(
ids int identity,
class nvarchar(10))
/استخراج جميع المجموعات من جدول ABC، وتخزينها مؤقتًا في متغير الجدول @tem/
insert into @tem(class)
select i
from abc
group by i
/حساب عدد الصفوف في متغير الجدول @tem/
select @count=@@rowcount
/تعيين قيمة متغير الدورات @looptime بالقيمة الابتدائية=1/
select @looptime=1
while(@looptime<=@count)
begin
/تعيين قيمة المجموعة إلى متغير @i/
select @i=class
from @tem
where ids=@looptime
/إدراج المجموعات الأولى 2 في متغير الجدول @abc/
insert into @abc
select top 2 *
from abc
where i=@i
order by price desc
/زيادة متغير الدورات @looptime ب1/
select @looptime=@looptime+1
end
/عرض النتائج/
select *
from @abc
order by i,price

4.
باستخدام السكين لمعالجة
الطريقة تشبه الطريقة الثالثة الخاصة بي، يمكن للجميع تجربتها

لقد كتبت 4 طرق، لا أعرف ما إذا كان لديكم أي طرق أخرى، يمكننا مناقشتها، شكراً لكم.

استخدمته اليوم، يمكن حل مشكلة حذف السجلات المكررة باستخدام هذا الأسلوب

بالطبع يجب أن يحتوي الجدول على مؤشر فريد، راقب التالي

حذف من dbo.TB_WorkflowTask a
 WHERE ItemID ليس في (استحصال top 1 ItemID من TB_WorkflowTask حيث TaskName = a.TaskName And EmpID = a.EmpID And BillTypeID =a.BillTypeID And BillID = a.BillID And Status =a.Status AND WFStatus =a.WFStatus )

ملاحظة: يمكن استخدام In أو Not in فقط، وليس Exists أو Not Exists، ولماذا، فكر في ذلك؟

مثال 10: كيف يمكنني الحصول على قيمة السجل الأخير بعد التجميع؟
 

لا يزال غامضاً، لنقم بترتيبه مرة أخرى:

أعيد ترتيب النسق:

الآن لدينا جدول Log: Day In Out Current
  2012.4.5 10 0 10
  2012.4.5 0 5 5
  2012.4.6 30 20 15
  2012.4.6 0 3 12

  ………………………………………………

آمل أن يتم عرضه كـ
،
  2012.4.5 10 5 5
  2012.4.6 30 23 12

كود SQL
مع tb كـ(
استحصل على [day], مجموع([in]) كـ [in], مجموع([out]) كـ out, مجموع([in]) - مجموع([out]) كـ [current], ترتيب() فوق(ترتيب [day]) كـ row من [log] بمجموع [day]
)
استحصل على [day], [in], [out], (من خلال استحصال مجموع [current] من tb b حيث b.row <= a.row)[current] من tb a
 
 
كود SQL
2012.4.5 10 5 5
2012.4.6 30 23 12
 
كود SQL
 
--> بيانات الاختبار: [Log]
إذا كان object_id('[Log]') غير صحيح فحذف جدول [Log]
create table [Log]([Day] date,[In] int,[Out] int,[Current] int)
insert [Log]
select '2012.4.5',10,0,10 union all
select '2012.4.5',0,5,5 union all
select '2012.4.6',30,20,15 union all
select '2012.4.6',0,3,12
 
select
[Day],sum([In]) [In],sum([Out]) [Out],min([Current]) as [Current]
من [Log] group by [Day]
 
/*
يوم الدخول الخروج الحالي
2012-04-05 10 5 5
2012-04-06 30 23 12
*/
 
مثال 11: إجماليات مزدوجة بعد التنسيق في SQL

https://ar.oldtoolbag.com/article/106074.htm

مثال 12: إحصاء التصنيف والتنسيق في SQL
تحتاج إلى معرفة كيفية استخدام بعض جمل SQL ومؤشرات الحساب لتنظيم بيانات SQL، مما يتيح لك تحليلها بشكل فعال. ستخبرك النصائح التالية كيفية بناء الجملة للحصول على النتائج التي تريدها.
قد يكون ترتيب البيانات بطريقة منطقية تحديًا. بعض الأحيان قد تحتاج فقط إلى تصنيف بسيط. عادةً، يجب عليك القيام بمعالجة أكثر - تنسيق البيانات لتحسين التحليل والإجماليات. بفضل SQL، يوفر العديد من الجمل والوظائف الحسابية والمؤشرات المستخدمة للتصنيف والتنسيق والإجماليات. ستساعدك النصائح التالية على فهم متى تقوم بالتصنيف، متى تقوم بالتنسيق، متى وكيف تقوم بالإجماليات. للحصول على تفاصيل كل جملة ومؤشر، يرجى الرجوع إلى
.
#1: ترتيب التصنيف
عادةً، نحتاج بالفعل إلى ترتيب جميع البيانات. جملة ORDER BY في SQL ترتب البيانات حسب الترتيب الأبجدي أو الرقمي. لذلك، تصنف البيانات المماثلة بوضوح إلى مجموعات مختلفة. ومع ذلك، هذه المجموعات هي نتائج تصنيف فقط وليست مجموعات حقيقية. يظهر ORDER BY كل سجل، بينما قد تمثل المجموعة عدة سجلات.
#2: تقليل البيانات المشابهة في المجموعة
الفرق بين التصنيف والتنسيق يكمن في: يظهر بيانات التصنيف (كل سجل في أي معيار محدد)而不ظهر بيانات التنسيق هذه. يقلل جملة GROUP BY من البيانات المشابهة في السجل الواحد. على سبيل المثال، يمكن لجملة GROUP BY أن تعيد قائمة برموز البريد المميزة الفريدة من تلك التي تحتوي على نفس القيم في ملف المصدر:
SELECT ZIP
FROM Customers
GROUP BY ZIP
تتضمن فقط الأعمدة التي تعبر عن المجموعات في GROUP BY وSELECT list. بمعنى آخر، يجب أن تتطابق قائمة SELECT مع قائمة GROUP. باستثناء حالة واحدة: يمكن أن تحتوي قائمة SELECT على الدوال التجميعية. (بينما لا تدعم GROUP BY الدوال التجميعية.)
تذكر، لا تقوم GROUP BY بتقسيم المجموعات التي يتم إنتاجها كنتائج. إذا كنت ترغب في ترتيب المجموعات حسب الترتيب الأبجدي أو الرقمي، أضف جملة ORDER BY subclause (#1). بالإضافة إلى ذلك، لا يمكنك استخدام اسم مجال آخر في جملة GROUP BY. يجب أن تكون الأعمدة المجمعة في البيانات الأساسية، ولكن لا يجب أن تظهر في النتائج.
#3: تحديد البيانات قبل التجميع
يمكنك إضافة جملة WHERE لتحديد البيانات التي يتم تجميعها. على سبيل المثال، الجملة التالية تعود إلى قائمة رموز البريدية للعملاء في منطقة كنتاكي فقط.
SELECT ZIP
FROM Customers
WHERE State = 'KY'
GROUP BY ZIP
تقوم WHERE بفیلتر البيانات قبل حساب القيم في جملة GROUP BY، تذكر هذا الأمر مهم.
مثل GROUP BY، لا يدعم WHERE الدوال التجميعية.
#4: العودة إلى جميع المجموعات
عند استخدام WHERE لفیلتر البيانات، يتم عرض المجموعات فقط لتلك السجلات التي تم تحديدها. لن تظهر البيانات التي تتوافق مع تعريف المجموعة ولكن لا تفي بشرط الجملة. بغض النظر عن شرط WHERE، إذا كنت ترغب في تضمين جميع البيانات، أضف جملة ALL subclause. على سبيل المثال، بإضافة ALL subclause إلى الجملة السابقة، سيتم العودة إلى جميع مجموعات الرموز البريدية، وليس فقط مجموعات منطقة كنتاكي.
SELECT ZIP
FROM Customers
WHERE State = 'KY'
GROUP BY ALL ZIP
بهذا الشكل، قد يسبب هذان الجملتان تضارباً، وقد لا تستخدم ALL subclause بهذه الطريقة. عند حساب قيمة عمود باستخدام التجميع، يكون استخدام ALL subclause مفيداً. على سبيل المثال، يحدد الجملة التالية عدد العملاء في كل رمز بريدي لكنتاكي، ويظهر أيضًا قيم الرموز البريدية الأخرى.
SELECT ZIP, Count(ZIP) AS KYCustomersByZIP
FROM Customers
WHERE State = 'KY'
GROUP BY ALL ZIP
تتكون المجموعات التي تحصل عليها من جميع قيم الرموز البريدية في البيانات الأساسية. ولكن، تظهر الأعمدة التجميعية (KYCustomerByZIP) كـ 0، لأن لا توجد أي مجموعات أخرى غير مجموعات رموز البريدية لكنتاكي.
لا يدعم الاستعلام البعيد GROUP BY ALL.
#5: تحديد البيانات بعد التجميع
WHERE جملة (#3) قبل جملة GROUP BY لحساب قيم البيانات. عند الحاجة إلى تحديد البيانات بعد التجميع، استخدم HAVING. عادةً، بغض النظر عما إذا كنت تستخدم WHERE أو HAVING، فإن النتائج متشابهة. ولكن تذكر، لا يمكن تبادل هاتين الجملتين، هذا أمر مهم. إذا كان لديك أي استفسار، هنا دليل تطبيقي: استخدم WHERE لفیلترين التسجيلات، واستخدم HAVING لفیلترين المجموعات.
في العادة، تستخدم HAVING لتحديد قيمة مجموعة باستخدام التجميع. على سبيل المثال، يظهر الجملة التالية قائمة بالبريديات، ولكن قد لا تحتوي هذه الجداول على جميع البريديات في المصدر الأساسي:
SELECT ZIP, Count(ZIP) AS CustomersByZIP
FROM Customers
GROUP BY ZIP
HAVING Count(ZIP) = 1
تظهر فقط تلك المجموعات التي تحتوي على عميل واحد في النتائج.
#6: معرفة WHERE وHAVING بشكل أفضل
إذا كنت لا تزال تشعر بالحيرة حول استخدام WHERE وHAVING، يمكنك تطبيق هذه الإرشادات التالية:
يظهر WHERE قبل GROUP BY؛ يحدد SQL قيمة WHERE قبل تجميع السجلات.
يظهر HAVING بعد GROUP BY؛ يحدد SQL قيمة HAVING بعد تجميع السجلات.
#7: استخدام التجميع لتحليل المجموعات
يساعد تقسيم البيانات في تحليل البيانات، ولكن في بعض الأحيان تحتاج أيضًا إلى معلومات غير المجموعات نفسها. يمكنك إضافة دالة تجميع لتحليل البيانات المجموعة. على سبيل المثال، يظهر الجملة التالية المجموعات الفرعية لكل مجموعة:
SELECT OrderID, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY OrderID
يجب أن تتطابق قائمة SELECT وGROUP BY مع بعضها البعض. الاستثناء الوحيد هو تضمين دالة تجميع في جملة SELECT.
#8: إجمالي التجميع
يمكنك إضافة مزيد من الت总计 إلى البيانات عن طريق عرض المجموعات الفرعية. يعرض عمود ROLLUP سجلاً إضافيًا لكل مجموعة، وهو المجموع. يتم حساب ذلك السجل باستخدام دالة التجميع لكل سجل في المجموعة. يظهر الجملة التالية المجموعات الفرعية لكل مجموعة.
SELECT Customer, OrderNumber, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY Customer, OrderNumber
WITH ROLLUP
سيعرض سطر ROLLUP لمجموعة تحتوي على القيم OrderTotal 20 و 25 قيمة OrderTotal 45. القيمة الأولى في نتائج ROLLUP هي فريدة لأنها تحسب قيمة جميع السجلات في المجموعة. تلك القيمة هي مجموع جميع السجلات في القاعدة.
لا يدعم ROLLUP استخدام جمل DISTINCT أو GROUP BY ALL في دالة التجميع.
#9: إجمالي كل عمود
ميزة CUBE أكثر تطورًا من ROLLUP، حيث يعود بمجموع كل قيمة في كل مجموعة. النتيجة مشابهة لـ ROLLUP، ولكن CUBE يشمل سجلاً إضافيًا لكل عمود في المجموعة. يظهر الجملة التالية المجموعات الفرعية لكل مجموعة وعدد إجمالي إضافي لكل عميل.
SELECT Customer, OrderNumber, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY Customer, OrderNumber
WITH CUBE
The totals obtained by CUBE are the most complex. Not only do they complete the aggregation and ROLLUP work, but they also calculate the values of other columns in the defined group. That is, CUBE totals every possible combination of columns.
CUBE does not support GROUP BY ALL.
#10: Sort totals
When the CUBE result is chaotic (usually it is), you can add a GROUPING function as shown below:
SELECT GROUPING(Customer), OrderNumber, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY Customer, OrderNumber
WITH CUBE
The result includes two additional values for each row.
Value 1 indicates that the value on the left is a total value - the result of the ROLLUP or CUBE operator.
Value 0 indicates that the value on the left is a detailed record produced by a GROUP BY subquery.

In grouping queries, the HAVING clause can also be used in conjunction to define query conditions.

Use group by for grouping queries

When using the group by keyword, the items that can be specified in the select list are limited, only the following items are allowed in the select statement:

〉is the column being grouped
〉returns an expression worth for each group, for example, using an aggregate function as a parameter of a column name


group by has a principle, that is, all columns after select without using aggregate functions must appear after group by (important)

group by example


Example 1

Data table:

Name Subject Score
Zhang San Chinese 80
Zhang San Math 98
Zhang San English 65
Li Si Chinese 70
Li Si Math 80
Li Si English 90

Expected query result:

Name Chinese Math English
Zhang San 80 98 65
Li Si 70 80 90

كود
 
create table testScore   
(   
   tid int primary key identity(1,1),   
   tname varchar(30) null,   
   ttype varchar(10) null,   
   tscor int null  
)   
go   

---插入数据   
insert into testScore values ('张三','语文',80)   
إدراج ('Zhang San', 'رياضيات', 98) في testScore   
إدراج ('Zhang San', 'إنجليزي', 65) في testScore   
إدراج ('Li Si', 'لغة عربية', 70) في testScore   
إدراج ('Li Si', 'رياضيات', 80) في testScore   
إدراج ('Li Si', 'إنجليزي', 90) في testScore   


اختيار tname كـ 'اسم',    
أقصى قيمة (حالة ttype WHEN 'لغة عربية' THEN tscor ELSE 0 END) 'لغة عربية',    
أقصى قيمة (حالة ttype WHEN 'رياضيات' THEN tscor ELSE 0 END) 'رياضيات',    
أقصى قيمة (حالة ttype WHEN 'إنجليزي' THEN tscor ELSE 0 END) 'إنجليزي'    
من testScore    
مجموعة حسب tname

مثال ثاني


هناك بيانات كالتالي: (لجعلها أكثر وضوحًا، لم أستخدم رموز البلدان، بل استخدمت أسماء البلدان كـ Primary Key)

الدولة (الدولة) السكان (السكان)
الصين 600
الولايات المتحدة 100
كندا 100
المملكة المتحدة 200
فرنسا 300
اليابان 250
ألمانيا 200
المكسيك 50
الهند 250

بناءً على بيانات عدد السكان لهذه البلاد، يجب أن نحصل على النتيجة التالية.

القارة السكان
آسيا 1100
شمال أمريكا 250
أخرى 700

كود

اختيار مجموع سكان,
    حالة country
        WHEN 'الصين' THEN 'آسيا'
        WHEN 'الهند' THEN 'آسيا'
        WHEN 'اليابان' THEN 'آسيا'
        WHEN 'الولايات المتحدة' THEN 'شمال أمريكا'
        WHEN 'كندا' THEN 'شمال أمريكا'
        WHEN 'المكسيك' THEN 'شمال أمريكا'
    ELSE 'أخرى' END
من جدول Table_A
مجموعة حسب حالة country
        WHEN 'الصين' THEN 'آسيا'
        WHEN 'الهند' THEN 'آسيا'
        WHEN 'اليابان' THEN 'آسيا'
        WHEN 'الولايات المتحدة' THEN 'شمال أمريكا'
        WHEN 'كندا' THEN 'شمال أمريكا'
        WHEN 'المكسيك' THEN 'شمال أمريكا'
    ELSE 'أخرى' END;

بالطبع، يمكننا أيضًا استخدام هذا الأسلوب لتحديد مستوى الراتب وتحديد عدد الأشخاص في كل مستوى. رمز SQL كالتالي;

اختيار
    حالة عندما يكون راتب <= 500 THEN '1'
       WHEN salary > 500 AND salary <= 600 THEN '2'
       WHEN salary > 600 AND salary <= 800 THEN '3'
       WHEN salary > 800 AND salary <= 1000 THEN '4'
    ELSE NULL END salary_class,
    عدد(*)
من جدول Table_A
مجموعة حسب
    حالة عندما يكون راتب <= 500 THEN '1'
       WHEN salary > 500 AND salary <= 600 THEN '2'
       WHEN salary > 600 AND salary <= 800 THEN '3'
       WHEN salary > 800 AND salary <= 1000 THEN '4'
    ELSE NULL END;

عادةً ما يتبع groupby اسم عمود، ولكن في هذا المثال، يجعل جملة case من التجميع أقوى.

مثال ثالث

هناك بيانات كالتالي

الدولة (الدولة) الجنس (الجنس) السكان (السكان)
الصين 1 340
الصين 2 260
الولايات المتحدة 1 45
الولايات المتحدة 2 55
كندا 1 51
كندا 2 49
المملكة المتحدة 1 40
المملكة المتحدة 2 60

عندما يتم فرز البيانات بناءً على الدولة والجنس، يظهر النتيجة كالتالي

الدولة الرجال النساء
الصين 340 260
الولايات المتحدة 45 55
كندا 51 49
المملكة المتحدة 40 60

كود

SELECT country,
    SUM( CASE WHEN sex = '1' THEN 
           population ELSE 0 END), -- عدد السكان الرجال
    SUM( CASE WHEN sex = '2' THEN 
           population ELSE 0 END)  -- عدد السكان النساء
FROM Table_A
GROUP BY country;

معالجة القيم NULL في جملة GROUP BY
ماذا إذا كانت هناك قيم NULL في عمود التجميع في جملة GROUP BY؟ في SQL، NULL ليس يساوي NULL (تمت مناقشته في جملة WHERE). ومع ذلك، في جملة GROUP BY، يتم جمع جميع القيم NULL في مجموعة واحدة، ويُعتبرون "متماثلين".

جملة HAVING
جملة GROUP BY تقوم بتجميع، فقط بناءً على بيانات العمود المختارة، تضع الصفوف التي لها نفس القيمة في مجموعة واحدة. ولكن في التطبيق العملي، غالبًا ما تحتاج إلى إزالة مجموعات الصف التي لا تلبية الشروط، لتحقيق هذه الوظيفة، يقدم SQL جملة HAVING. ويبدو الجملة كالتالي.

SELECT عمود, SUM(عمود)
FROM جدول
GROUP BY عمود
HAVING SUM(عمود) شرط قيمة

شرح: HAVING عادةً يستخدم مع جملة GROUP BY. بالطبع، يمكن أن تكون دالة SUM() أي أي دالة تجميع أخرى. يطبق DBMS شرط البحث في جملة HAVING على مجموعات الصف التي تولدها جملة GROUP BY، إذا لم تكن مجموعات الصف تلبية شرط البحث، يتم إزالة هذه المجموعات من جدول النتائج.

تطبيق جملة HAVING
استعلام من جدول TEACHER للحصول على الأقسام التي تحتوي على على الأقل اثنين من المدرسين وكذلك عدد المدرسين.

كود التنفيذ:

SELECT DNAME, COUNT(*) AS num_teacher
FROM TEACHER
GROUP BY DNAME
HAVING COUNT(*)>=2

مميزات جملة HAVING ومميزات جملة WHERE

تماثل جملة HAVING مع جملة WHERE في أنها تحدد الشروط البحثية أيضًا، ولكن يختلف الأمر عن جملة WHERE، حيث أن جملة HAVING مرتبطة بالمجموعات وليس بالسطر الفردي.
1- إذا تم تحديد جملة GROUP BY، فإن الشروط البحثية التي تحددها جملة HAVING ستتأثير على المجموعات التي أنشأتها جملة GROUP BY.
2- إذا تم تحديد جملة WHERE وليس جملة GROUP BY، فإن الشروط البحثية التي تحددها جملة HAVING ستتأثير على الخروج من جملة WHERE، ويتم اعتبار هذا الخروج كنوع من المجموعات.
3- إذا لم يتم تحديد جملة GROUP BY ولا جملة WHERE، فإن الشروط البحثية التي تحددها جملة HAVING ستتأثير على الخروج من جملة FROM، ويتم اعتبار هذا الخروج كنوع من المجموعات.
4- في جملة SELECT، ترتيب تنفيذ WHERE وHAVING مختلف. يمكن العثور على خطوات تنفيذ جملة SELECT في فصل 5.1.2 من الكتاب، حيث يمكن لجملة WHERE أن تأخذ الدخول من جملة FROM فقط، بينما يمكن لجملة HAVING أن تأخذ الدخول من جملة GROUP BY، WHERE وFROM.

تعليمية الأساس
أنت قد تعجبك