如何在没有联合的情况下编写以下查询?或者我可以使用简单的子查询或使用连接编写以下查询吗?

时间:2016-12-29 10:34:25

标签: sql querydsl

如何在没有联合的情况下编写以下查询?或者我可以使用简单的子查询或使用连接编写以下查询吗? 我的要求是我必须使用querydsl获取结果。由于querydsl不支持工会运作。我想用连接编写下面的查询然后使用querydsl调用它。         //以下查询用于获取车队日历详细信息

    SELECT * FROM
              (SELECT V.ID AS VID,
                V.MODEL,
                V.VIN,
                V.EXTERIOR_COLOR,
                V.LICENSE_PLATE,
                V.CURRENT_LOCATION,
                V.NOTES,
                C.ID AS CID,
                //PFIS_COMMON_OPS.FORMATNAME concatnating the name
                PFIS_COMMON_OPS.FORMATNAME(C.FIRST_NAME,C.LAST_NAME,C.MIDDLE_NAME,2) AS JOURNALIST_NAME ,
                C.LICENSE_AFFI_NAME  AS AFNAME,
                L.DATE_OUT  AS DAYOUT,
                L.DATE_IN   AS DAYIN,
                NULL  AS HOLD,
                ''   AS REASONS,
                NULL AS ADATE,
                L.LOAN_TYPE_ID  AS TYPEID
              FROM PFIS_VEHICLE_DETAILS V,
                PFIS_CONTACT C,
                PFIS_VEHICLE_CONTACT_LOAN L
              WHERE C.ID          =L.CONTACT_ID
              AND V.ID            =L.VEHICLE_ID
              AND L.LOAN_TYPE_ID IN (1,5)
              AND ( L.DATE_IN BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY')
              OR L.DATE_OUT BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY'))
            -- AND LOWER(V.CURRENT_LOCATION) = 'new york'
              UNION
        --fetch from data for status-Id=5
              SELECT V.ID AS VID,
                V.MODEL,
                V.VIN,
                V.EXTERIOR_COLOR,
                V.LICENSE_PLATE,
                V.CURRENT_LOCATION,
                V.NOTES,
                0                  AS CID,
                ''                 AS JOURNALIST_NAME ,
                ''                 AS AFNAME,
                NULL               AS DAYOUT,
                NULL               AS DAYIN ,
                S.ON_HOLD_TILL     AS HOLD,
                S.REASONS_FOR_HOLD AS REASONS,
                S.ANTICIPATED_DATE AS ADATE,
                -1                 AS TYPEID
              FROM PFIS_VEHICLE_DETAILS V,
                PFIS_VEHICLE_DETAIL_STATUS S
              WHERE V.ID     =S.VEHICLE_ID
              AND S.STATUS_ID=4
              AND ( S.ANTICIPATED_DATE BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY')
              OR S.ON_HOLD_TILL BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY'))
              --AND LOWER(V.CURRENT_LOCATION) = 'new york'
            )

提前致谢...

1 个答案:

答案 0 :(得分:0)

如果既不支持UNION也不支持INCLUDE,则不会有简单的答案。

对FROM和WHERE子句进行以下更改应该可以解决问题。 注意我强烈建议您养成使用JOIN子句的习惯,而不是在WHERE子句中混合使用连接条件和过滤器。它有点冗长,但如果使用体面的格式,则更容易阅读和发现错误。

  

请记住,这是假设,因为您还没有提供样本数据:每个PFIS_VEHICLE_DETAILS行在联合的第一部分或第二部分最多出现一次;从来没有。否则,你必须多做一些工作才能让你的行在必要时加倍。

FROM    PFIS_VEHICLE_DETAILS V
        /* First part of union. LEFT JOIN bc presumably rows aren't expected to match rows from second part of union. */
        LEFT JOIN (
                /* Use subquery to filter bc values would be NULL in non matching rows. */
                SELECT  *
                FROM    PFIS_VEHICLE_CONTACT_LOAN L
                WHERE   L.LOAN_TYPE_ID IN (1, 5)
                    AND (   L.DATE_IN BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY')
                        OR  L.DATE_OUT BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY'))
                ) L ON
            V.ID = L.VEHICLE_ID
        LEFT JOIN PFIS_CONTACT C ON
            C.ID = L.CONTACT_ID
        /* Second part of union */
        LEFT JOIN (
                SELECT  *
                FROM    PFIS_VEHICLE_DETAIL_STATUS S
                WHERE   S.STATUS_ID=4
                    AND (   S.ANTICIPATED_DATE BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY')
                        OR  S.ON_HOLD_TILL BETWEEN TO_DATE('04/01/2014','DD/MM/YYYY') AND TO_DATE('05/10/2014','DD/MM/YYYY'))
                ) S ON
            V.ID = S.VEHICLE_ID

如果上述方法无效,则使用UNION模拟FULL OUTER JOIN的方法很复杂,可以更普遍地应用。 但它变得混乱 - 你可能想要考虑是否正在使用正确的工具来完成工作;即放弃该工具,转而支持 支持UNION。

方法是使用FULL OUTER JOIN构建一个结合了2个union-parts(我们将调用U1和U2)的结果集,类似于以下内容:

U1.C1 U1.C2 U2.C1 U2.C2 JOIN_COL
1-1   xx    NULL  NULL  U1
1-2   yy    NULL  NULL  U1
1-3   zz    NULL  NULL  U1
NULL  NULL  2-1   aa    U2
NULL  NULL  2-2   bb    U2
NULL  NULL  2-3   cc    U2

然后您将U1.C1U2.C1合并,同样U1.C2U2.C2合并。

您的查询结构类似于以下内容:

SELECT  u1.C1, u1.C2, u2.C1, u2.C2, COALESCE(u1.JOIN_COL, u2.JOIN_COL) as JOIN_COL
FROM    (   /* JOIN_COL is important as it allows joining U1 and U2 without matching rows */
            SELECT  'U1' as JOIN_COL,
                    C1, C2, ...
            FROM    ... 
        ) u1 /* Subquery for part of "union" */
        FULL OUTER JOIN (
            SELECT  'U2' as JOIN_COL,
                    C1, C2, ...
            FROM    ... 
        ) u2 ON /* Subquery for part of "union" */
            u1.JOIN_COL = u2.JOIN_COL

给定的SELECT演示了对象的第一部分。将其替换为以下内容以获得最终的模拟UNION。

SELECT  COALESCE(u1.C1, u2.C1) as C1,
        COALESCE(u1.C2, u2.C2) as C2,
        ... /* Note JOIN_COL obviously not needed in final output */