简体   繁体   English

MySQL多级嵌套案例什么时候优先?

[英]MySQL Multi level nested CASE WHEN THEN ELSE with priority?

I am trying to wrap my mind around this little problem I've run into. 我正在努力解决遇到的这个小问题。

I am joining multiple tables containing vehicle information (so make, model, type, subtype, part numbers and part titles) in order to go through my "title override" table that might (or might not) contain entries where certain vehicle parts would have their title overwritten in certain cases, for certain vehicle makes, models, types or subtypes. 我要加入多个包含车辆信息(因此,制造商,型号,类型,子类型,零件号和零件标题)的表,以便浏览我的“标题覆盖”表,该表可能(或可能不)包含某些车辆零件应具有的条目在某些情况下,对于某些车辆品牌,型号,类型或子类型,其标题将被覆盖。

As in, think of using standard oil for all BMW cars, and then for BMW M5 there is an exception that overrides that standard oil with another premium oil. 例如,考虑对所有宝马汽车都使用标准机油,然后对于BMW M5,有一个例外,那就是用另一种高级机油替代该标准机油。 Or say standard oil is being used for all cars UNLESS otherwise specified in this table. 或说,除非本表另有规定,否则所有汽车均使用标准机油。 And the priority goes down the list: 优先级在列表中:

  • specific model (highest priority) 特定型号(最高优先级)
  • specific make (2nd highest priority) 具体品牌(第二优先)
  • subtype (3rd highest priority) 子类型(第3个最高优先级)

So the override table ("ov") looks something like this: 因此,覆盖表(“ ov”)如下所示:

id | type_id | make_id | subtype_id | model_id | part_id | part_override
1  |   2     |    0    |    0       |    0     |   33    |  Global-Replacement-Oil
2  |   2     |    1    |    0       |    0     |   33    |  Yamaha-Premium-Oil
3  |   2     |    0    |    2       |    0     |   33    |  Global-Dirtbike-Oil
4  |   2     |    1    |    4       |    0     |   33    |  Yamaha-Streetbike-Oil
5  |   2     |    0    |    0       |   199    |   33    |  Yamaha-R6-2015-Oil

** type_id = 2 is for motorcycles, type_id = 3 is for cars, for example **例如,type_id = 2适用于摩托车,type_id = 3适用于汽车

** if make_id, subtype_id or model_id are = 0 that means that override should apply to all makes, subtypes and models, unless value <> 0 is specified. **如果make_id,subtype_id或model_id为= 0,则表示覆盖应适用于所有品牌,子类型和模型,除非指定值<> 0。

And for that part_id = 33, I only need to display it once in my results, not multiple times, depending on which model is queried in the application and where it fits in that "matrix". 对于那个part_id = 33,我只需要在结果中显示一次即可,而无需多次显示,这取决于在应用程序中查询的模型以及该“矩阵”中的位置。

So if I am running this query on Yamaha R6 2015 edition and need to pull the code/title for that part_id=33 for that model, "model_id" column has the highest priority over all the other ones, so I'll ignore all the other ones and show title for record #5. 因此,如果我在Yamaha R6 2015版本上运行此查询,并且需要为该模型提取该part_id = 33的代码/标题,则“ model_id”列的优先级高于所有其他模型,因此我将忽略所有其他的,并显示记录#5的标题。

If I however pick another Yamaha Street bike, the highest priority match I'd get would be record #4 (as it's got both make_id and subtype_id defined). 但是,如果我选择另一辆Yamaha Street自行车,我得到的最高优先级比赛将是记录#4(因为同时定义了make_id和subtype_id)。

Or if I pick a random Dirtbike, I'll get a match on record #3 (on subtype_id), so that code/title will display instead. 或者,如果我选择一个随机的越野车,我将在记录#3(在subtype_id上​​)得到一个匹配项,因此将显示代码/标题。

And then if I pick any Yamaha bike, I'll get a match on record #2 (on make_id). 然后,如果我选择任何一辆Yamaha自行车,我都会在记录#2(在make_id上​​)获得一场比赛。

And at last, if none of those are specified and I just pick a random bike, it will show record #1 instead, as that will make a match on type_id alone (bikes = 2). 最后,如果未指定任何一项,而我只是选择了一辆随机自行车,它将显示记录#1,因为这将单独对type_id进行匹配(自行车= 2)。

This is the query that I have so far (or part of it): 这是我到目前为止(或其一部分)的查询:

SELECT DISTINCT
CASE 
  WHEN p.part_id = '72' AND ov.part_override != "" AND ov.type_id = p.type_id AND 
    (CASE 
      WHEN ov.model_id IS NOT NULL 
      THEN ov.model_id = "$MODEL_ID"
      ELSE 
        CASE 
          WHEN ov.make_id != 0 
          THEN ov.make_id = m.make_id
          ELSE
            CASE 
              WHEN ov.subtype_id != 0 
              THEN ov.subtype_id = st.subtype_id 
              ELSE 1 
            END
         END
      END)
  THEN ov.part_override
  ELSE p.part_number 
END part_number,
ov.make_id,
....
FROM parts p ON ...
INNER JOIN makes m ON p.make_id = m.make_id
INNER JOIN ... 
(just joining a bunch of other separate tables that contain all types,
subtypes, models and so on, respectively - irrelevant for the logic above)

What I am getting with this query is all the parts that apply to a specific model listed, so if I run it for a specific model like Yamaha R6 2015 I'll get the records #1,2 and 5 come up. 我从该查询中得到的是列出的适用于特定模型的所有零件,因此,如果我针对诸如Yamaha R6 2015之类的特定模型运行它,则会得到记录#1,2和5。 But I just need record #5 to show up, as explained above, in the order of importance and priority. 但是如上所述,我只需要记录#5以重要性和优先级的顺序显示即可。

If I do a GROUP BY part_id or something like that then I only get one record showing, but it's not necessarily the right one, in terms of highest priority. 如果我执行GROUP BY part_id或类似的操作,那么我只会显示一条记录,但就最高优先级而言,它不一定是正确的记录。

What am I missing? 我想念什么?

Or how can I cascade this whole importance/priority check down that query, so that while going through all the parts records in other joined tables and filtering it based on this override ("ov") table it only spits out the highest priority record, based on some sort of a waterfall or cascade rule? 或者,我该如何级联整个重要性/优先级检查该查询,以便在浏览其他联接表中的所有零件记录并基于此覆盖(“ ov”)表对其进行过滤时,它只会吐出最高优先级的记录,基于某种瀑布式或级联规则?

Not sure how to write that, or if it's even possible. 不知道该怎么写,或者甚至可能。

Or if I have to run it as a recurring stored procedure of sorts, that's fine too. 或者,如果我必须将其作为某种定期存储过程运行,那也很好。

Thanks! 谢谢!

Without seeing more accurately your other table joins, nor the actual table name you have here, you might want something with multiple left-joins to the override table, then pull COALESCE based on the first FOUND value. 在没有更准确地看到其他表联接或此处没有实际表名的情况下,您可能想要某些具有多个左联接的对象到重写表,然后根据第一个FOUND值提取COALESCE。 Something like.. 就像是..

select
      ...
      coalesce( P_OV.part_override, M_OV.part_override,
             MOD_OV.part_override, P.PartName ) as FinalPartName
   from
      Parts P
         left join PartsOverride P_OV
            on p.id = P_OV.part_id
         join make m
            on p.make_id = m.make_id
            left join PartsOverride M_OV
               on m.make_id = M_OV.make_id
         join model mo
            on p.model_id = mo.model_id
            left join PartsOverride MOD_OV
               on m.make_id = MOD_OV.make_id

Then, you can change the order of priority of which "OV" version you want within the coalesce(). 然后,您可以在coalesce()中更改所需的“ OV”版本的优先级顺序。 So if Model is higher priority than make: 因此,如果Model的优先级高于make:

  coalesce( MOD_OV.part_override, M_OV.part_override,
         P_OV.part_override, P.PartName ) as FinalPartName

Whichever field is NOT NULL FIRST WINS. 无论哪个字段都不是NULL优先。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM