تحسين استعلام MySQL مع جملة كبيرة في () أو انضم إلى جدول مشتق

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

سؤال

دعنا نقول أنني بحاجة إلى الاستعلام عن شركاء الشركة. لدي جدول ، "المعاملات" ، التي تحتوي على بيانات عن كل معاملة تم إجراؤها.

CREATE TABLE `transactions` (
  `transactionID` int(11) unsigned NOT NULL,
  `orderID` int(11) unsigned NOT NULL,
  `customerID` int(11) unsigned NOT NULL,
  `employeeID` int(11) unsigned NOT NULL, 
  `corporationID` int(11) unsigned NOT NULL,
  PRIMARY KEY (`transactionID`),
  KEY `orderID` (`orderID`),
  KEY `customerID` (`customerID`),
  KEY `employeeID` (`employeeID`),
  KEY `corporationID` (`corporationID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

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

على سبيل المثال ، إذا كان الموظفون A و B من Corporation 1 يشاركان في بيع مكنسة كهربائية للشركة 2 ، فسيكون هناك سجلان في جدول "المعاملات" ؛ واحد لكل موظف ، وكلاهما للشركة 1. يجب ألا يؤثر هذا على النتائج. يجب معاملة التجارة من الشركة 1 ، بغض النظر عن عدد موظفيها ، على أنها واحدة.

من السهل ، اعتقدت. سأقوم فقط بالانضمام إلى طاولة مشتقة ، مثل ذلك:

SELECT corporationID FROM transactions JOIN (SELECT DISTINCT orderID FROM transactions WHERE corporationID = 1) AS foo USING (orderID)

يعيد الاستعلام قائمة الشركات التي شاركت في التداولات مع الشركة 1. هذا بالضبط ما أحتاجه ، لكنه بطيء للغاية لأن MySQL لا يمكنه استخدام مؤشر CorporationId لتحديد الجدول المشتق. أفهم أن هذا هو الحال بالنسبة لجميع الجداول الفرعية/المشتقة في MySQL.

لقد حاولت أيضًا الاستعلام عن مجموعة من OrderIDs بشكل منفصل واستخدام جملة كبيرة بشكل يبعث على السخرية () (Typhically 100 000+ ids) ، ولكن كما اتضح أن MySQL لديه مشاكل تستخدم مؤشرات على شروط كبيرة يبعث على السخرية () ونتيجة لا تتحسن وقت الاستعلام.

هل هناك أي خيارات أخرى متاحة ، أم قمت بالإرهاق كل منهما؟

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

المحلول

إذا فهمت متطلباتك ، فيمكنك تجربة ذلك.

select distinct t1.corporationID
from transactions t1
where exists (
    select 1
    from transactions t2
    where t2.corporationID =  1
    and t2.orderID = t1.orderID)
and t1.corporationID != 1;

أو هذا:

select distinct t1.corporationID
from transactions t1
join transactions t2
on t2.orderID = t1.orderID
and t1.transactionID != t2.transactionID
where t2.corporationID = 1
and t1.corporationID != 1;

نصائح أخرى

لا معنى لها لبياناتك ، أعتقد أنك تستخدم CorporationId حيث تعني معرف العميل في مرحلة ما هناك ، حيث ينضم استعلامك إلى جدول المعاملات إلى جدول المعاملات لـ CorporationId = 1 استنادًا إلى OrderID للحصول على الشركات ... أيهما سيكون 1 ، أليس كذلك؟

هل يمكنك تحديد ما يعنيه العميل ، الموظف ، و CorporationIDs؟ كيف أعرف أن الموظفين A و B هم من Corporation 1 - في هذه الحالة ، هل الشركة 1 هي CorporationId ، و Corporation 2 هي العميل ، وهي مخزنة في العميل؟

إذا كان هذا هو الحال ، فأنت بحاجة فقط إلى القيام بمجموعة:

SELECT customerID
FROM transactions
WHERE corporationID = 1
GROUP BY customerID

(أو حدد وتجمع من OrderId إذا كنت تريد صفًا واحدًا لكل طلب بدلاً من صف واحد لكل عميل.)

باستخدام المجموعة ، فأنت تتجاهل حقيقة أن هناك سجلات متعددة مكررة باستثناء الموظف.

على العكس ، لإرجاع جميع الشركات التي بيعت إلى الشركة 2.

SELECT corporationID
FROM transactions
WHERE customerID = 2
GROUP BY corporationID
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top