يتم تنفيذ MySQL CASE "Else Case When" عندما يكون الشرط المسبق صحيحًا - ما الذي أفتقده؟

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

  •  06-07-2019
  •  | 
  •  

سؤال

لدي جدول، نظرًا لنظام الطرف الثالث الذي نستخدمه، يحتوي أحيانًا على بيانات مكررة.نظرًا لأن النموذج يستخدم طريقة EAV، فلا توجد طريقة لتصفية هذا بالطريقة "الصحيحة"، لذلك أقوم بتجميع البيانات في طريقة عرض - أعلم أن هذه مشكلة في جمع البيانات ولكن من الأسهل بالنسبة لي إصلاحها على نهاية العرض بدلاً من ذلك المرور عبر هذا النظام وربما كسر البيانات والنماذج الموجودة.أحتاج إلى التحقق من أحد الحقلين لمعرفة ما إذا تم إدخال أحدهما أو كليهما، ولكن اختر واحدًا فقط (وإلا فسيتم عرض الاسم مرتين على النحو التالي:"جون، جون" بدلاً من "جون" فقط).إليك الكود الخاص بي للجزء ذي الصلة:

group_concat(
(
  case when (`s`.`fieldid` = 2) then `s`.`data` 
  else
    case when (`s`.`fieldid` = 35) then `s`.`data` 
    else NULL end 
  end
) separator ','),_utf8'') as first_name

إذا تم إدخال كل من fieldid 2 وfieldid 35، أتوقع أن يؤدي هذا إلى إرجاع القيمة من fieldid = 2 فقط وليس القيمة من fieldid = 35، نظرًا لأنه لا ينبغي تنفيذ جملة Else عندما تكون الحالة الأصلية صحيحة.ومع ذلك، فإنه يستحوذ على ذلك، ثم يستمر في تنفيذ الحالة عندما يكون داخل جملة else؟

كيف يمكنني إصلاح هذا الرمز ليعطيني إما fieldid = 2 أو fieldid = 35، مع تجنب جمعهما معًا مما يؤدي إلى تكرار الاسم؟

يحرر

وهنا هيكل الجدول:

table: subscribers_data
subscriberid (int)   fieldid (int)   data (text)    

يستخدم بنية E-A-V لذلك قد يكون سجل العينة:

subscriberid          fieldid         data
1                     2               John
1                     3               Smith
1                     35              John
1                     36              Smith

مع كون معرف الحقل 2 و35 هو الحقل المخصص "الاسم الأول" (المحدد في جدول منفصل) ومعرف الحقل 3 و36 هو "اسم العائلة".

إليك العرض الكامل الذي أستخدمه:

select `ls`.`subscriberid` AS `id`,
left(`l`.`name`,(locate(_utf8'_',`l`.`name`) - 1)) AS `user_id`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 2) then `s`.`data` 
    when (`s`.`fieldid` = 35) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `first_name`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 3) then `s`.`data` 
    when (`s`.`fieldid` = 36) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `last_name`,
ifnull(`ls`.`emailaddress`,_utf8'') AS `email_address`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 81) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `mobile_phone`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 100) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `sms_only` 
from ((`list_subscribers` `ls` 
join `lists` `l` on((`ls`.`listid` = `l`.`listid`))) 
left join `subscribers_data` `s` on((`ls`.`subscriberid` = `s`.`subscriberid`))) 
where (left(`l`.`name`,(locate(_utf8'_',`l`.`name`) - 1)) regexp _utf8'[[:digit:]]+') 
group by `ls`.`subscriberid`,`l`.`name`,`ls`.`emailaddress`

يتم استخدام العرض كنموذج لتطبيق Ruby on Rails، لذلك أستخدم بعض الاختراقات الإبداعية لتزييف "user_id" الذي تتوقعه Rails (نقوم بتسمية الحقل list.name في جدول القوائم باستخدام معرف رقمي يتم إنشاء تطبيق Rails للواجهة الأمامية لدينا عندما نضيف مستخدمًا جديدًا، لذلك أقوم باستخراج هذا الرقم فقط لجعل العرض يبدو وكأنه جدول قاعدة بيانات لاتفاقية Rails)

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

المحلول

أي شيء في الداخل group_concat() ليس لديه طريقة لرؤية السياق الذي يتم تشغيله فيه.إذن، لديك صفين في مجموعة واحدة، أحدهما به fieldid=2 والثانية مع fieldid=35, ، فسوف يقوم بما يلي:

  • صف المعالجة مع fieldid=2...
    • s.fieldid = 2 صحيح، العودة s.data
  • صف المعالجة مع fieldid=35...
    • s.fieldid = 2 غير صحيح، حاول else جزء
    • s.fieldid = 35 صحيح، العودة s.data

وهذا ما يفسر سبب إرجاع "جون" عدة مرات.الطريقة الوحيدة لإصلاحها هي تشغيل استعلام مختلف خارج group_concat().

يحرر:

يجب عليك حقًا القيام بذلك بهذه الطريقة، استخدم شيئًا مثل هذا بدلاً من ذلك:

SELECT ...
   min(CASE WHEN s.fieldid IN (2,35) THEN s.data ELSE NULL END) AS first_name
...

بدلا من ذلك يمكنك القيام به group_concat(DISTINCT ...) إذا كانت القيمتان لا يمكن أن تكونا مختلفتين (وإلا فسوف تحصل على سبيل المثال:"جون، جوني").لماذا لديك قيمتان لـ first_name/last_name بالرغم من ذلك؟

نصائح أخرى

أنا لست رجل MySQL، ولكن في بيان حالة خادم SQL، يمكنك القيام بذلك دون أول "آخر"

case
  when fieldid = 2 then data
  when fieldid = 35 then data
  else null
end

ويبدو أيضًا أنك تعيد نفس حقل "البيانات" في كلتا الحالتين

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