嵌套的JOIN创建自定义动态列

时间:2019-10-29 14:47:05

标签: mysql

我有一个这样的桌子 veicoli (车辆):

-------------------------------
| ID  |   Modello |   Targa   | 
-------------------------------
| 1   |   IVECO   |   XA123WE |     
-------------------------------
| 2   |   IVECO   |   CF556XD |   
-------------------------------
| 3   |   FIAT    |   AS332ZZ | 
-------------------------------
| 4   |   GOLF    |   GF567YU | 
-------------------------------

对于我没有的每辆车,一个或多个 revisioni_veicolo (修订)(DateExpiring较大的那是我需要根据版本检查修订是否仍然有效的一种)今天的日期)

-------------------------------------------------------------------
| ID  |   veicoli_ID   |   DateExpiring         |     Pass_Success |
-------------------------------------------------------------------
| 1   |   1            | 2019-07-01             |        1
------------------------------------------------------------------
| 2   |   1            | 2020-10-01             |        0
-------------------------------------------------------------------
| 3   |   2            | 2019-11-25             |        1
-------------------------------------------------------------------
| 4   |   2            | 2018-10-20             |        1
-------------------------------------------------------------------
| 5   |   4            | 2017-10-20             |        1
-------------------------------------------------------------------

基于我上面的示例(今天是2019-10-29 ):

车辆:ID = 1的修订版仍处于活动状态(2020-10-01),但未通过(Pass_success = 0)

车辆:ID = 2的修订版仍然有效(2019-11-25)并通过(Pass_success = 1)

车辆:ID = 3尚未修订

车辆:ID = 4具有修订版本,但没有有效的修订版本(最后过期于2017-10-20),但最后一个通过了检查(Pass_success = 1)

我需要在查询结果中动态创建3个新的自定义列:

-------------------------------------------------------------------------------------------
| ID  |   Modello |   Targa   |  RevisionPresent | RevisionStillActive | LastRevisionPassed |
-------------------------------------------------------------------------------------------
| 1   |   IVECO   |   XA123WE |      true        |   true              |   false  
-------------------------------------------------------------------------------------------
| 2   |   IVECO   |   CF556XD |      true        |   true              |   true
-------------------------------------------------------------------------------------------
| 3   |   FIAT    |   AS332ZZ |       false      |   false             |  false
-------------------------------------------------------------------------------------------
| 4   |   GOLF    |   GF567YU |       true       |   false             |  true
-------------------------------------------------------------------------------------------

我试图从我的旧帖子开始:MYSQL INNER JOIN to get 3 types of result

但是我很困惑使用嵌套JOIN

我尝试开始摆弄小提琴,但是我陷入语法错误:http://sqlfiddle.com/#!9/3c70bf/2

3 个答案:

答案 0 :(得分:1)

您需要表的左联接和条件聚合:

select v.ID, v.Modello, v.Targa,
  max(r.DataScadenzaRevisione is not null) RevisionPresent,
  coalesce(max(r.DataScadenzaRevisione >= current_date()), 0) RevisionStillActive,
  max(case when r.DataScadenzaRevisione = g.maxdate then r.EsitoPositivo else 0 end) LastRevisionPassed 
from veicoli v 
left join revisioni_veicolo r on r.veicoli_ID = v.id
left join (
  select veicoli_id, max(DataScadenzaRevisione) maxdate 
  from revisioni_veicolo
  group by veicoli_id
) g on g.veicoli_ID = v.id           
group by v.ID, v.Modello, v.Targa

请参见demo
结果:

| ID  | Modello | Targa   | RevisionPresent | RevisionStillActive | LastRevisionPassed |
| --- | ------- | ------- | --------------- | ------------------- | ------------------ |
| 1   | IVECO   | XA123WE | 1               | 1                   | 0                  |
| 2   | IVECO   | CF556XD | 1               | 1                   | 1                  |
| 3   | FIAT    | AS332ZZ | 0               | 0                   | 0                  |
| 4   | GOLF    | GF567YU | 1               | 0                   | 1                  |

答案 1 :(得分:0)

...
LEFT JOIN (SELECT a.veicoli_ID, a.EsitoPositivo AS StatoUltimaRevisione,
  a.DataScadenzaRevisione FROM revisioni_veicolo) a
...

这有两件事。

  • 为此子查询定义了别名a,因此您不能在子查询中引用它。但是无论如何您都不需要限定该子查询中的列-您没有在其他子查询中进行此操作,因此我不确定在这种情况下为什么要这样做。
  • 您没有任何加入条件。对于何时需要加入条件,MySQL有点不一致。但是在这种情况下,您需要一个。

在通过这两个更正测试完查询后,它可以正常工作。

答案 2 :(得分:0)

基本上,您只需要查看每个车辆的最新版本即可生成该结果集。

您可以使用相关子查询进行过滤:

select
    v.ID,
    v.Modello,
    v.Targa,
    (DataScadenzaRevisione >= now()) RevisionPresent,
    (DataScadenzaRevisione >= now() and EsitoPositivo = 1) RevisionStillActive,
    (EsitoPositivo = 1) LastRevisionPassed 
from 
    veicoli v
    left join revisioni_veicolo r 
        on r.veicoli_ID = v.ID
        and r.DataScadenzaRevisione = (
            select max(DataScadenzaRevisione) 
            from revisioni_veicolo r1 
            where r1.veicoli_ID = v.ID
    )

您可以在this db fiddle中将示例数据与结果一起检查。

或者您可以使用窗口函数(这需要MySQL 8.0):

select
    v.ID,
    v.Modello,
    v.Targa,
    (DataScadenzaRevisione >= now()) RevisionPresent,
    (DataScadenzaRevisione >= now() and EsitoPositivo = 1) RevisionStillActive,
    (EsitoPositivo = 1) LastRevisionPassed 
from (
    select 
        v.*, 
        r.*, 
        row_number() over(partition by ID order by r.DataScadenzaRevisione desc) rn
    from veicoli v
    left join revisioni_veicolo r on r.veicoli_ID = v.ID
) where coaelesce(rn, 1) = 1