لماذا يجبرني SQL على تكرار كافة الحقول غير المجمعة من عبارة SELECT الخاصة بي في عبارة GROUP BY الخاصة بي؟[مغلق]

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

  •  03-07-2019
  •  | 
  •  

سؤال

لقد أزعجني هذا لفترة طويلة.

في 99% من الحالات، تكون جملة GROUP BY نسخة طبق الأصل من عبارة SELECT، مطروحًا منها الدوال المجمعة (MAX، SUM، وما إلى ذلك).
وهذا يكسر مبدأ عدم تكرار نفسك.

متى لا يمكن أن تحتوي جملة GROUP BY على نسخة طبق الأصل من جملة SELECT مطروحًا منها الوظائف المجمعة؟

يحرر

أدرك أن بعض التطبيقات تسمح لك بالحصول على حقول مختلفة في GROUP BY عنها في SELECT (وبالتالي 99%، وليس 100%)، ولكن بالتأكيد هذا استثناء بسيط جدًا؟
هل يمكن لأي شخص أن يشرح ما الذي من المفترض أن يتم إرجاعه إذا كنت تستخدم حقولًا مختلفة؟

شكرًا.

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

المحلول

أميل إلى الاتفاق معك - هذه إحدى الحالات العديدة التي يجب أن يكون لدى SQL إعدادات افتراضية أكثر ذكاءً قليلاً لتوفير بعض الكتابة علينا جميعًا.على سبيل المثال، تخيل لو كان هذا قانونيًا:

Select ClientName, InvoiceAmount, Sum(PaymentAmount) Group By *

حيث تعني "*" "كافة الحقول غير المجمعة".إذا عرف الجميع أن هذه هي الطريقة التي تسير بها الأمور، فلن يكون هناك أي ارتباك.يمكنك الاشتراك في قائمة محددة من الحقول إذا كنت تريد القيام بشيء صعب، ولكن splat تعني "كلهم" (وهو ما يعني في هذا السياق، كل ممكن تلك).

من المؤكد أن "*" تعني شيئًا مختلفًا هنا عما هو موجود في جملة SELECT، لذلك ربما يعمل حرف مختلف بشكل أفضل:

Select ClientName, InvoiceAmount, Sum(PaymentAmount) Group By !

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

نصائح أخرى

ولأنهم هما شيئان مختلفان، يمكنك تجميع من قبل العناصر التي ليست في بند حدد

وتحرير:

وأيضا، هل هي آمنة لجعل هذا الافتراض؟

ولدي بيان SQL

Select ClientName, InvAmt, Sum(PayAmt) as PayTot

هل "تصحيح" للملقم لنفترض أريد أن مجموعة من CLIENTNAME وINVOICEAMOUNT؟ أنا شخصيا أفضل (وأعتقد أنه أكثر أمانا) أن يكون هذا الرمز

Select ClientName, InvAmt, Sum(PayAmt) as PayTot
Group By ClientName

ورمي خطأ، مما دفع لي لتغيير رمز إلى

Select ClientName, Sum(InvAmt) as InvTot, Sum(PayAmt) as PayTot
Group By ClientName

وآمل / نتوقع سنرى شيئا أكثر شمولا في وقت قريب؛ سيكون درسا في التاريخ SQL حول هذا الموضوع أن تكون مفيدة وغنية بالمعلومات. أي واحد؟ أي واحد؟ Bueller؟

في هذه الأثناء، وأنا يمكن أن نلاحظ ما يلي:

وSQL يسبق مبدأ جاف، على الأقل بقدر ما هو موثق في مبرمج عملي .

لا تتطلب كل بالواجبات القائمة الكاملة: سايبيس، على سبيل المثال، سيتم تنفيذ بسعادة الاستفسارات مثل

SELECT a, b, COUNT(*)
FROM some_table
GROUP BY a

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

وربما نحن بحاجة إلى شكل الاختزال - نسميها GroupSelect

GroupSelect Field1, Field2, sum(Field3) From SomeTable Where (X = "3")

وبهذه الطريقة، محلل حاجة رمي فقط خطأ إذا ترك من وظيفة الكلية.

وهذا سبب وجيه لذلك هو أنك سوف تحصل على نتائج غير صحيحة في كثير من الأحيان لا إذا لم يتم تحديد كافة الأعمدة. افترض أن لديك ثلاثة أعمدة، col1، col2 وcol3.

لنفترض البيانات الخاصة بك يبدو مثل هذا:

Col1  Col2 Col3
a      b    1
a      c    1
b      b    2
a      b    3

وselect col1, col2, sum(col3) from mytable group by col1, col2
من شأنه أن يعطي النتائج التالية:

Col1  Col2 Col3
a      b    4
a      c    1
b      b    2

وكيف سيكون تفسير
select col1, col2, sum(col3) from mytable group by col1

وتخميني سيكون

Col1  Col2 Col3
a      b    5
a      c    5
b      b    2

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

وشخصيا أنا سعيد أن group by يتطلب المجالات.

وأنا أتفق مع GROUP BY ALL، GROUP BY *، أو شيئا من هذا القبيل. كما ذكر في آخر الأصلي، في 99٪ (وربما أكثر) من الحالات تريد تجميع جميع غير المجمعة الأعمدة / التعبيرات.

لكن

وهنا مثال واحد حيث كنت في حاجة GROUP BY الأعمدة، لأسباب التوافق.

SELECT 
  MIN(COUNT(*)) min_same_combination_cnt, 
  MAX(COUNT(*)) max_same_comb_cnt, 
  AVG(COUNT(*)) avg_same_comb_cnt, 
  SUM(COUNT(*)) total_records,
  COUNT(COUNT(*)) distinct_combinations_cnt
FROM <some table>
GROUP BY <list of columns>

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

وسيكون من الجميل أن تقدم باقتراح لهذا التحسن إلى مستوى SQL. أنا لا أعرف كيف يعمل.

في الواقع، لا أن تكون 100٪ من الوقت؟ هناك حالة من الحالات التي يمكن أن يكون هناك عمود (غير مجموع المباراتين) في اختيار هذا ليس في GROUP BY؟

وأنا لا أملك جوابا على الرغم من. ومن المؤكد أنه يبدو وكأنه لحظة محرجة للغة.

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

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top