[英]LEFT OUTER JOIN on same table returns 0 records
我已經在其他帖子上搜索了我的問題,但沒有任何效果。
我有一個包含客戶的表和餐廳的營業額預測數據,計划值和已實現值都在同一表中(必須與以前的數據庫保持一致)。
我需要獲得特定餐廳(站點)和特定活動(餐廳,外賣店,單擊“ n收集”)以及日期范圍(通常是一個月)的過去一年的計划的預測和已實現的預測。
我的問題是,當計划的預測不存在並且實現的最后一年存在時,請求什么也不會返回。
這是我的要求:
SELECT
P.AFO_ACTIVITY_ID,
P.AFO_SITE_ID,
P.AFO_FORECAST_DATE,
P.AFO_SERVICE_ID,
P.AFO_PLANNED_CUSTOMERS,
P.AFO_REALIZED_CUSTOMERS,
P.AFO_GROUP_CUSTOMERS,
P.AFO_PLANNED_TURNOVER,
P.AFO_REALIZED_TURNOVER,
P.AFO_GROUP_TURNOVER,
P.AFO_NB_EMPLOYEES,
P.AFO_TURNOVER_EMPLOYEES,
P.AFO_ID,
p2.AFO_REALIZED_CUSTOMERS AS REAL_CUSTOMERS_PREVIOUS_YEAR,
p2.AFO_REALIZED_TURNOVER AS REAL_TURNOVER_PREVIOUS_YEAR
FROM
ACT_FORECAST P
LEFT OUTER JOIN
act_forecast p2 ON p2.AFO_FORECAST_DATE = p.AFO_FORECAST_DATE - 364
AND p2.AFO_SITE_ID = p.AFO_SITE_ID
AND p2.AFO_ACTIVITY_ID = p.AFO_ACTIVITY_ID
AND p2.AFO_SERVICE_ID = p.AFO_SERVICE_ID
WHERE
P.AFO_SITE_ID = :siteid
AND P.AFO_ACTIVITY_ID = :activityid
AND P.AFO_FORECAST_DATE BETWEEN :startdate AND :enddate
如果我播放2018年2月的請求,我將有我的數據(2018年和2017年)。
但是,如果我在2019年2月播放它,則一無所有,這對於該年的計划部分是可以的,因為尚未完成預測,但對於上一年的部分,我應該有一些數據。
我也嘗試過RIGHT OUTER JOIN,但沒有任何結果。
樣本數據 :
ActivityId SiteId ForecastDate ServiceId PlannedCustomers RealizedCustomers GroupCustomers PlannedTurnover RealizedTurnover GroupTurnover NbEmployeeMeal TurnoverEmployeeMeal ID RealizedCustomersPreviousYear RealizedTurnoverPreviousYear
1 58 01/02/18 1 0 0 0 0 11 0 0 11 2953773 0 39,85
1 58 01/02/18 3 345 398 0 3467,25 4052,01 0 0 0 2953774 328 3291,53
1 58 01/02/18 5 10 16 0 140 194,04 0 16 60,9 2953775 7 91,12
1 58 01/02/18 7 125 151 0 1200 1413,93 0 0 0 2953776 112 1063,89
有任何想法嗎?
問候
您的where
子句僅在您指定范圍內的P
中查找記錄。 如果沒有,有沒有源行至左從外連接。
您可以通過內聯視圖或CTE生成您正在查看的時段內的所有可能日期,然后查找與任一日期集匹配的記錄:
WITH CTE (this_year, last_year) AS (
SELECT :startdate + level - 1, :startdate + level - 365
FROM dual
CONNECT BY level <= :enddate - :startdate + 1
)
SELECT
:activityid AS AFO_ACTIVITY_ID,
:siteid AS AFO_SITE_ID,
CTE.this_year AS AFO_FORECAST_DATE,
P.AFO_SERVICE_ID,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_PLANNED_CUSTOMERS END) AS AFO_PLANNED_CUSTOMERS,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_REALIZED_CUSTOMERS END) AS AFO_REALIZED_CUSTOMERS,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_GROUP_CUSTOMERS END) AS AFO_GROUP_CUSTOMERS,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_PLANNED_TURNOVER END) AS AFO_PLANNED_TURNOVER,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_REALIZED_TURNOVER END) AS AFO_REALIZED_TURNOVER,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_GROUP_TURNOVER END) AS AFO_GROUP_TURNOVER,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_NB_EMPLOYEES END) AS AFO_NB_EMPLOYEES,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_TURNOVER_EMPLOYEES END) AS AFO_TURNOVER_EMPLOYEES,
MAX(CASE WHEN P.AFO_FORECAST_DATE = this_year
THEN P.AFO_ID END) AS AFO_ID,
MAX(CASE WHEN P.AFO_FORECAST_DATE = last_year
THEN P.AFO_REALIZED_CUSTOMERS END) AS REAL_CUSTOMERS_PREVIOUS_YEAR,
MAX(CASE WHEN P.AFO_FORECAST_DATE = last_year
THEN P.AFO_REALIZED_TURNOVER END) AS REAL_TURNOVER_PREVIOUS_YEAR
FROM
CTE
JOIN
ACT_FORECAST P
ON
P.AFO_FORECAST_DATE = CTE.this_year
OR
P.AFO_FORECAST_DATE = CTE.last_year
WHERE
P.AFO_SITE_ID = :siteid
AND P.AFO_ACTIVITY_ID = :activityid
GROUP BY
:activityid,
:siteid,
CTE.this_year,
P.AFO_SERVICE_ID;
與其嘗試外部聯接(無論哪種方式),它都不是尋找兩年中的特定日期,而是進行一種手動樞紐操作,以在右側欄中顯示相關年份的價值。 注意最后兩列的表達式使用last_year
,其余的使用this_year
(分組的除外)。
對於SERVICE_ID
,如果今年沒有值,則可能希望合並以獲取上一年的值。 如果不想看到空值,也可以將其他值合並為零。
如果您不想使用WITH
子句,則可以使用內聯視圖:
SELECT
...
FROM
(
SELECT :startdate + level - 1 AS this_year,
:startdate + level - 365 AS last_year
FROM dual
CONNECT BY level <= :enddate - :startdate + 1
) CTE
JOIN
ACT_FORECAST P
...
盡管您可能想要一個比CTE
更具描述性的名稱(使用任一版本...)
將樣本數據重新整理為CTE后,問題中未顯示的值將為空:
with act_forecast (afo_activity_id, afo_site_id, afo_forecast_date, afo_service_id,
afo_planned_customers, afo_realized_customers, afo_group_customers,
afo_planned_turnover, afo_realized_turnover, afo_group_turnover,
afo_nb_employees, afo_turnover_employees, afo_id)
as (
select 1, 58, date '2018-02-01', 1, 0, 0, 0, 0, 11, 0, 0, 11, 2953773 from dual
union all select 1, 58, date '2017-02-02', 1, null, 0, null, null, 39.85, null, null, null, null from dual
union all select 1, 58, date '2018-02-01', 3, 345, 398, 0, 3467.25, 4052.01, 0, 0, 0, 2953774 from dual
union all select 1, 58, date '2017-02-02', 3, null, 328, null, null, 3291.53, null, null, null, null from dual
union all select 1, 58, date '2018-02-01', 5, 10, 16, 0, 140, 194.04, 0, 16, 60.9, 2953775 from dual
union all select 1, 58, date '2017-02-02', 5, null, 7, null, null, 91.12, null, null, null, null from dual
union all select 1, 58, date '2018-02-01', 7, 125, 151, 0, 1200, 1413.93, 0, 0, 0, 2953776 from dual
union all select 1, 58, date '2017-02-02', 7, null, 112, null, null, 1063.89, null, null, null, null from dual
)
然后在2018年給出的范圍是:
AFO_ACTIVITY_ID AFO_SITE_ID AFO_FORECA AFO_SERVICE_ID AFO_PLANNED_CUSTOMERS AFO_REALIZED_CUSTOMERS AFO_GROUP_CUSTOMERS AFO_PLANNED_TURNOVER AFO_REALIZED_TURNOVER AFO_GROUP_TURNOVER AFO_NB_EMPLOYEES AFO_TURNOVER_EMPLOYEES AFO_ID REAL_CUSTOMERS_PREVIOUS_YEAR REAL_TURNOVER_PREVIOUS_YEAR
--------------- ----------- ---------- -------------- --------------------- ---------------------- ------------------- -------------------- --------------------- ------------------ ---------------- ---------------------- ---------- ---------------------------- ---------------------------
1 58 2018-02-01 3 345 398 0 3467.25 4052.01 0 0 0 2953774 328 3291.53
1 58 2018-02-01 7 125 151 0 1200 1413.93 0 0 0 2953776 112 1063.89
1 58 2018-02-01 1 0 0 0 0 11 0 0 11 2953773 0 39.85
1 58 2018-02-01 5 10 16 0 140 194.04 0 16 60.9 2953775 7 91.12
並在2019年實現以下目標:
AFO_ACTIVITY_ID AFO_SITE_ID AFO_FORECA AFO_SERVICE_ID AFO_PLANNED_CUSTOMERS AFO_REALIZED_CUSTOMERS AFO_GROUP_CUSTOMERS AFO_PLANNED_TURNOVER AFO_REALIZED_TURNOVER AFO_GROUP_TURNOVER AFO_NB_EMPLOYEES AFO_TURNOVER_EMPLOYEES AFO_ID REAL_CUSTOMERS_PREVIOUS_YEAR REAL_TURNOVER_PREVIOUS_YEAR
--------------- ----------- ---------- -------------- --------------------- ---------------------- ------------------- -------------------- --------------------- ------------------ ---------------- ---------------------- ---------- ---------------------------- ---------------------------
1 58 2019-01-31 3 398 4052.01
1 58 2019-01-31 5 16 194.04
1 58 2019-01-31 1 0 11
1 58 2019-01-31 7 151 1413.93
如果我理解正確,則可以使用FULL OUTER JOIN
:
SELECT
COALESCE(P.AFO_ACTIVITY_ID, P2.AFO_ACTIVITY_ID) as AFO_ACTIVITY_ID,
COALESCE(P.AFO_SITE_ID, P2.AFO_SITE_ID) as AFO_SITE_ID,
P.AFO_FORECAST_DATE,
P.AFO_SERVICE_ID,
P.AFO_PLANNED_CUSTOMERS,
P.AFO_REALIZED_CUSTOMERS,
P.AFO_GROUP_CUSTOMERS,
P.AFO_PLANNED_TURNOVER,
P.AFO_REALIZED_TURNOVER,
P.AFO_GROUP_TURNOVER,
P.AFO_NB_EMPLOYEES,
P.AFO_TURNOVER_EMPLOYEES,
P.AFO_ID,
p2.AFO_REALIZED_CUSTOMERS AS REAL_CUSTOMERS_PREVIOUS_YEAR,
p2.AFO_REALIZED_TURNOVER AS REAL_TURNOVER_PREVIOUS_YEAR
FROM (SELECT P.*
FROM ACT_FORECAST P
WHERE P.AFO_SITE_ID = :siteid AND
P.AFO_ACTIVITY_ID = :activityid AND
P.AFO_FORECAST_DATE BETWEEN :startdate AND :enddate
) P FULL JOIN
(SELECT p2.*
FROM act_forecast p2
WHERE P2.AFO_SITE_ID = :siteid AND
P2.AFO_ACTIVITY_ID = :activityid AND
P2.AFO_FORECAST_DATE BETWEEN :startdate - 364 AND :enddate - 364
) p2
ON p2.AFO_FORECAST_DATE = p.AFO_FORECAST_DATE - 364 AND
p2.AFO_SITE_ID = p.AFO_SITE_ID AND
p2.AFO_ACTIVITY_ID = p.AFO_ACTIVITY_ID AND
p2.AFO_SERVICE_ID = p.AFO_SERVICE_ID
我很驚訝地看到- 364
(我的專業知識可能少於您的專業知識),並期望:
p.AFO_FORECAST_DATE - INTERVAL 364 DAY
也許這被解釋為(微)秒?
(典型的調試是通過省略部分條件,例如在AFO_FORECAST_DATE。)
像下面這樣使用東西:
SELECT P.AFO_ACTIVITY_ID,
P.AFO_SITE_ID,
P.AFO_FORECAST_DATE,
P.AFO_SERVICE_ID,
P.AFO_PLANNED_CUSTOMERS,
P.AFO_REALIZED_CUSTOMERS,
P.AFO_GROUP_CUSTOMERS,
P.AFO_PLANNED_TURNOVER,
P.AFO_REALIZED_TURNOVER,
P.AFO_GROUP_TURNOVER,
P.AFO_NB_EMPLOYEES,
P.AFO_TURNOVER_EMPLOYEES,
P.AFO_ID,
p2.AFO_REALIZED_CUSTOMERS AS REAL_CUSTOMERS_PREVIOUS_YEAR,
p2.AFO_REALIZED_TURNOVER AS REAL_TURNOVER_PREVIOUS_YEAR
FROM ACT_FORECAST P
LEFT OUTER JOIN(SELECT DISTINCT p2.AFO_FORECAST_DATE
FROM ACT_FORECAST P2)
ON p2.AFO_FORECAST_DATE = p.AFO_FORECAST_DATE - 364
AND p2.AFO_SITE_ID = p.AFO_SITE_ID
AND p2.AFO_ACTIVITY_ID = p.AFO_ACTIVITY_ID
AND p2.AFO_SERVICE_ID = p.AFO_SERVICE_ID
WHERE
P.AFO_SITE_ID = :siteid
AND P.AFO_ACTIVITY_ID = :activityid
AND P.AFO_FORECAST_DATE BETWEEN :startdate AND :enddate
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.