在SELECT查询中填写缺少的月份

时间:2019-03-28 15:41:13

标签: sql oracle

我正在尝试在SELECT查询中填写缺少的月份。 看起来像这样:

SELECT sl.loonperiode_dt, (sum(slr.uren)) code_220
FROM HR.soc_loonbrief_regels slr,
             HR.soc_loonbrieven sl,
             HR.werknemers w,
             HR.v_kontrakten vk 
WHERE sl.loonperiode_dt BETWEEN '01012018' AND '01122018'
         AND slr.loon_code_id IN (394)
         AND slr.loonbrief_id = sl.loonbrief_id
         AND w.werknemer_id   = sl.werknemer_id
         AND w.werknemer_id   = vk.werknemer_id
         AND vk.functie_id    IN (121, 122, 128)
         AND sl.loonperiode_dt BETWEEN hist_start_dt AND last_day(nvl(hist_eind_dt, sl.loonperiode_dt))
         AND w.afdeling_id  like '961'
GROUP BY sl.loonperiode_dt
ORDER BY sl.loonperiode_dt

它输出此表:

31/01/18    234
30/04/18    245,8
31/05/18    714,6
31/07/18    288,04
31/08/18    281
30/11/18    515,12

我显然希望这样:

31/01/18    234
28/02/18    0
31/03/18    0
30/04/18    245,8
31/05/18    714,6
30/06/18    0
31/07/18    288,04
31/08/18    281
30/09/18    0
31/10/18    0
30/11/18    515,12
31/12/18    0

我有一个日历表“ CONV_HC.calendar ”,该表的日期位于名为“ DAT ”的列中。 我已经看到了很多与此有关的问题和答案,但是我不知道如何将LEFT JOIN方法或任何其他方法应用于当前问题。

非常感谢

1 个答案:

答案 0 :(得分:1)

您可能已经有一个包含月份的表,并与之“联接”,按日期分组,或者您可以通过子查询或使用 with 语句创建一个表,例如

WITH Months (month) AS (
  SELECT 1 AS Month FROM DUAL

  UNION ALL

  SELECT MONTH + 1
  FROM Months
  WHERE MONTH < 12
)
SELECT *
FROM Months

    LEFT JOIN SomeTable
    ON SomeTable.month = Months.MONTH
    --ON Extract(MONTH FROM SomeTable.date) = Months.MONTH

编辑

一个更好的例子:

--Just to simulate some table data
WITH SomeData AS (
  SELECT TO_DATE('01/01/2019', 'MM/DD/YYYY') AS Dat, 5 AS Value FROM dual
  UNION ALL
  SELECT TO_DATE('01/05/2019', 'MM/DD/YYYY') AS Dat, 7 AS Value FROM dual
  UNION ALL
  SELECT TO_DATE('03/03/2019', 'MM/DD/YYYY') AS Dat, 2 AS Value FROM dual
  UNION ALL
  SELECT TO_DATE('11/05/2019', 'MM/DD/YYYY') AS Dat, 9 AS Value FROM dual
)
, Months (StartDate, MaxYear) AS (
  SELECT CAST(TO_DATE('01/01/2019', 'MM/DD/YYYY') AS DATE) AS StartDate, 2019 AS MaxYear FROM DUAL

  UNION ALL

  SELECT CAST(ADD_MONTHS(StartDate, 1) AS DATE), MaxYear
  FROM Months
  WHERE EXTRACT(YEAR FROM ADD_MONTHS(StartDate, 1)) <= MaxYear 
)
SELECT
    Months.StartDate AS Dat
    , SUM(SomeData.Value) AS SumValue 
FROM Months

    LEFT JOIN SomeData
    ON Extract(MONTH FROM SomeData.Dat) = Extract(MONTH FROM Months.StartDate)

GROUP BY 
    Months.StartDate

编辑

您不会找到过去的解决方案的复制品,您需要从中获取想法并更改您的上下文。

让我们尝试一下。您可以在APP中“添加”缺少的月份,也可以将其与已经完成的表合并,而不必是真正的表,您可以创建一个表。 with 语句就是一个示例。因此,让我们获得2019年最后一天的所有月份:

--Geting the last day of every month for 2019
WITH Months (CurrentMonth, MaxYear) AS (
  SELECT CAST(TO_DATE('01/01/2019', 'MM/DD/YYYY') AS DATE) AS CurrentMonth, 2019 AS MaxYear FROM DUAL

  UNION ALL

  SELECT CAST(ADD_MONTHS(CurrentMonth, 1) AS DATE), MaxYear
  FROM Months
  WHERE EXTRACT(YEAR FROM ADD_MONTHS(CurrentMonth, 1)) <= MaxYear  
)
SELECT LAST_DAY(Months.CurrentMonth) AS LastDay
FROM Months

好的,现在我们所有的月份都可以参加。在您的查询中,您已经完成了总和,因此让我们跳过总和并仅使用您的数据。只需添加另一个 with 查询即可。

--Geting the last day of every month for 2018
WITH Months (CurrentMonth, MaxYear) AS (
  SELECT CAST(TO_DATE('01/01/2018', 'MM/DD/YYYY') AS DATE) AS CurrentMonth, 2018 AS MaxYear FROM DUAL

  UNION ALL

  SELECT CAST(ADD_MONTHS(CurrentMonth, 1) AS DATE), MaxYear
  FROM Months
  WHERE EXTRACT(YEAR FROM ADD_MONTHS(CurrentMonth, 1)) <= MaxYear  
)
, YourData as (
    SELECT sl.loonperiode_dt, (sum(slr.uren)) code_220
    FROM HR.soc_loonbrief_regels slr,
                 HR.soc_loonbrieven sl,
                 HR.werknemers w,
                 HR.v_kontrakten vk 
    WHERE sl.loonperiode_dt BETWEEN '01012018' AND '01122018'
             AND slr.loon_code_id IN (394)
             AND slr.loonbrief_id = sl.loonbrief_id
             AND w.werknemer_id   = sl.werknemer_id
             AND w.werknemer_id   = vk.werknemer_id
             AND vk.functie_id    IN (121, 122, 128)
             AND sl.loonperiode_dt BETWEEN hist_start_dt AND last_day(nvl(hist_eind_dt, sl.loonperiode_dt))
             AND w.afdeling_id  like '961'
    GROUP BY sl.loonperiode_dt
    --ORDER BY sl.loonperiode_dt
)
SELECT
    LAST_DAY(Months.CurrentMonth) AS LastDay
    , COALESCE(YourData.code_220, 0) AS code_220
FROM Months

    Left Join YourData
    on Extract(MONTH FROM Months.CurrentMonth) = Extract(MONTH FROM YourData.loonperiode_dt)
    --If you have more years: AND Extract(YEAR FROM Months.CurrentMonth) = Extract(YEAR FROM YourData.loonperiode_dt)

ORDER BY LastDay ASC