ماي - اختيار العمود ليس في المجموعة حسب

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

  •  06-07-2019
  •  | 
  •  

سؤال

وأنا أحاول لإضافة ميزات إلى تطبيق قبل الإيجاد وجئت عبر الخلية عرض شيء من هذا القبيل:

SELECT
     AVG(table_name.col1),
     AVG(table_name.col2),
     AVG(table_name.col3),
     table_name.personID,
     table_name.col4
FROM table_name
GROUP BY table_name.personID;

وOK ذلك هناك عدد قليل من الوظائف الإجمالية. يمكنك تحديد personID لأنك تجمع به. ولكنه أيضا هو اختيار العمود الذي ليس في وظيفة الكلية وليس جزءا من جملة GROUP BY. كيف يكون هذا ممكنا؟؟؟ هل مجرد اختيار قيمة عشوائية لأن القيم هي بالتأكيد ليست فريدة من نوعها لكل مجموعة؟

من أين آتي (MSSQL خادم)، وهذا خطأ. يمكن للشخص أن يفسر هذا السلوك بالنسبة لي، والسبب هو مسموح به في الخلية؟

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

المحلول

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

وهذه الاستعلامات ليست غامضة إذا اخترت فقط الأعمدة التي تعتمد على العمود (ق) في GROUP BY معايير وظيفيا. وبعبارة أخرى، إذا كان يمكن أن يكون هناك واحد فقط قيمة مميزة من عمود "غامض" في القيمة التي تحدد المجموعة، لا توجد مشكلة. هذا من شأنه أن الاستعلام سيكون غير قانوني في Microsoft SQL Server (وANSI SQL)، على الرغم من أنها لا يمكن أن يؤدي منطقيا في الغموض:

SELECT AVG(table1.col1), table1.personID, persons.col4
FROM table1 JOIN persons ON (table1.personID = persons.id)
GROUP BY table1.personID;

وأيضا، الخلية لديه واسطة SQL لجعلها تتصرف في المعيار: <لأ href = "http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by" يختلط = "noreferrer"> ONLY_FULL_GROUP_BY

وFWIW، سكليتي يسمح أيضا هذه مجموعة غامضة BY شروط، لكنه يختار قيمة من <م> آخر التوالي في المجموعة. <سوب> †


<سوب> † على الأقل في النسخة اختبرت. ماذا يعني أن تكون <م> تعسفية هو إما أن الخلية أو سكليتي يمكن تغيير تنفيذها في المستقبل، وبعض سلوك مختلف. ولذلك ينبغي عليك عدم الاعتماد على سلوك البقاء أنها النحو الذي هي عليه حاليا في حالات غامضة من هذا القبيل. فمن الأفضل لإعادة كتابة الاستفسارات الخاصة بك لتكون حتمية وليس غامضة. هذا هو السبب في تمكن الخلية 5.7 الآن ONLY_FULL_GROUP_BY افتراضيا.

نصائح أخرى

وأرجو أن يكون غوغلد لفترة أطول قليلا ... يبدو أنني وجدت <لأ href = "http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns. أتش تي أم أل "يختلط =" noreferrer "> جوابي .

<اقتباس فقرة>   

والخلية يمتد استخدام GROUP BY ذلك   يمكنك استخدام الأعمدة nonaggregated   أو العمليات الحسابية في قائمة SELECT   التي لا تظهر في GROUP BY   الشرط. يمكنك استخدام هذه الميزة ل   الحصول على أفضل أداء من خلال تجنب   لا لزوم له عمود الفرز و   التجمع. على سبيل المثال، لا تحتاج   إلى المجموعة على customer.name في   بعد الاستعلام

     

في SQL القياسية، سيكون لديك لإضافة   customer.name إلى GROUP BY جملة.   في الخلية، واسم لا لزوم لها.

ومع ذلك، يبدو أن مجرد ... خطأ.

select * from personel where p_id IN(select
min(dbo.personel.p_id)
FROM
personel
GROUP BY dbo.personel.p_adi)

ودعونا نقول لديك استفسار عن مثل هذا:

SELECT g, v 
FROM t
GROUP BY g;

في هذه الحالة، لكل قيمة ممكنة للg، الخلية يختار واحدة من القيم المناظرة من v.

ولكن، والتي يتم اختيار واحد، يعتمد على بعض الظروف.

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

وهذا هو قبيح جدا لأن السجلات في الجدول يجب أن يعامل على أنه تحديد حيث ترتيب العناصر يجب أن لا يهم. وهذا هو الحال "الخلية العش" ...

إذا كنت تريد تحديد قيمة v للحفاظ على، تحتاج إلى تطبيق subselect لt مثل هذا:

SELECT g, v 
FROM (
    SELECT * 
        FROM t 
        ORDER BY g, v DESC
) q
GROUP BY g;

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

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

SELECT g, v 
FROM (
    SELECT * 
        FROM t 
        WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9' 
        ORDER BY g, v DESC
) q
GROUP BY g;

وهذا هو ما كنت تتوقع، المرشحات subselect وأوامر الجدول. إنها تحافظ على السجلات حيث g لديها قيمة معينة، وإرجاع الاستعلام الخارجية التي g والقيمة الأولى لv.

ولكن، إذا قمت بإضافة نفس شرط WHERE إلى الاستعلام الخارجي ثم تحصل على نتيجة غير القطعية:

SELECT g, v 
FROM (
    SELECT * 
        FROM t 
        -- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9' 
        ORDER BY g, v DESC
) q
WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g;

والمثير للدهشة، يمكنك الحصول على قيم مختلفة لv عند تنفيذ نفس الاستعلام مرارا وتكرارا وهو ... غريب. السلوك المتوقع للحصول على كافة السجلات في الترتيب المناسب من فرعي، وتصفية لهم في الاستعلام الخارجي ومن ثم اختيار نفسه كما حصل في المثال السابق. ولكن لم يحدث ذلك.

ويختار قيمة v على ما يبدو عشوائيا. عاد الاستعلام نفس قيم مختلفة لv لو إعدام المزيد (~ 20) مرات ولكن كان توزيع يست موحدة.

إذا بدلا من إضافة الخارجي WHERE، قمت بتحديد شرط بصعوبات مثل هذا:

SELECT g, v 
FROM (
    SELECT * 
        FROM t1 
        -- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9' 
        ORDER BY g, v DESC
) q
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g
HAVING g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9';

وبعد ذلك تحصل على سلوك متناسقة مرة أخرى.

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

واختبرته مع هذه البيانات:

CREATE TABLE t1 (
    v INT,
    g VARCHAR(36)
);

INSERT INTO t1 VALUES (1, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');
INSERT INTO t1 VALUES (2, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');

وفي الخلية 5.6.41.

وربما انها مجرد الخلل الذي يحصل / حصلت ثابتة في الإصدارات الأحدث، يرجى إعطاء ردود فعل إذا كان لديك تجربة مع إصدارات أحدث.

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