SQL SelfJoin + Left Outer JOIN 日历
SQL SelfJoin + Left Outer JOIN Calendar
我收到了一个 SelfJoin 查询
;WITH t as
(
SELECT
ROW_NUMBER() OVER (ORDER BY dbo.DIM_PROJECT_TECH_OBJ.FUNCTIONAL_LOCATION,DATEADD(ms, DATEDIFF(ms, '00:00:00', CONVERT(VARCHAR,REPLACE(dbo.FACT_MEASUREMENT.Doc_Time,'24:00:00','23:59:59'),102)), CONVERT(DATETIME, dbo.DIM_TIME_USAGE.DATE)) ASC) AS Rowy,
dbo.FACT_MEASUREMENT.FACT_MEASUREMENT_KEY,
dbo.FACT_MEASUREMENT.Doc_Number,
dbo.FACT_MEASUREMENT.Created_By,
dbo.FACT_MEASUREMENT.Text,
dbo.FACT_MEASUREMENT.Doc_Time,
dbo.FACT_MEASUREMENT.Date_Loaded,
dbo.DIM_VC_MEASURE.VALUATION_CODE_AND_DESC,
dbo.DIM_TIME_USAGE.DATE,
dbo.DIM_PROJECT_TECH_OBJ.FUNCTIONAL_LOCATION,
dbo.DIM_VC_MEASURE.VALUATION_CODE,
CONVERT(VARCHAR,REPLACE(dbo.FACT_MEASUREMENT.Doc_Time,'24:00:00','23:59:59'),102) AS TIME,
DATEADD(ms, DATEDIFF(ms, '00:00:00', CONVERT(VARCHAR,REPLACE(dbo.FACT_MEASUREMENT.Doc_Time,'24:00:00','23:59:59'),102)), CONVERT(DATETIME, dbo.DIM_TIME_USAGE.DATE)) AS DATUM
FROM
dbo.DIM_PROJECT_TECH_OBJ INNER JOIN dbo.FACT_MEASUREMENT ON (dbo.FACT_MEASUREMENT.PROJECT_TECH_OBJ_KEY=dbo.DIM_PROJECT_TECH_OBJ.PROJECT_TECH_OBJ_KEY)
INNER JOIN dbo.DIM_TIME_USAGE ON (dbo.FACT_MEASUREMENT.TIME_KEY=dbo.DIM_TIME_USAGE.TIME_KEY)
INNER JOIN dbo.DIM_VC_MEASURE ON (dbo.DIM_VC_MEASURE.VALUATION_CODE_KEY=dbo.FACT_MEASUREMENT.VALUATION_CODE_KEY)
WHERE
dbo.FACT_MEASUREMENT.Measurement_Position = 'AVAILABILITY'
AND
dbo.DIM_PROJECT_TECH_OBJ.FUNCTIONAL_LOCATION IN ('XXX','YYY','ZZZ')
)
select t.*, tprev.DATUM AS PRE_DATUM, tprev.VALUATION_CODE AS PRE_CODE, DATEDIFF (minute,tprev.DATUM, t.DATUM) AS DELTA_MIN
from t join
t tprev
on tprev.rowy = t.rowy - 1 AND tprev.FUNCTIONAL_LOCATION = t.FUNCTIONAL_LOCATION ;
这将return一组字段
FUNTIONAL LOC DATUM CODE PRE_DATUM PRE_CODE (-> Other fields)
XXX 01/07/2015 A 06/06/2015 Y
XXX 05/07/2015 B 01/07/2015 A
XXX 10/07/2015 C 05/07/2015 B
YYY 03/07/2015 B 15/06/2015 K
YYY 09/07/2015 C 03/07/2015 B
YYY 15/07/2015 A 09/07/2015 C
现在我想创建一个带有日历(从 01/07 到 10/07 的图像)日期的外部连接并获得类似的东西:
FUNTIONAL LOC DATUM CODE PRE_DATUM PRE_CODE
XXX 01/07/2015 A 06/06/2015 Y
XXX 02/07/2015 06/06/2015 Y
XXX 03/07/2015 06/06/2015 Y
XXX 04/07/2015 06/06/2015 Y
XXX 05/07/2015 B 01/07/2015 A
XXX 06/07/2015 01/07/2015 A
XXX 07/07/2015 01/07/2015 A
XXX 08/07/2015 01/07/2015 A
XXX 09/07/2015 01/07/2015 A
XXX 10/07/2015 C 05/07/2015 B
YYY 01/07/2015 15/06/2015 K
YYY 02/07/2015 15/06/2015 K
YYY 03/07/2015 B 15/06/2015 K
YYY 09/07/2015 C 03/07/2015 B
YYY 10/07/2015 03/07/2015 B
基本上当在日历数据上找不到代码时使用上一个。
有suggestion/idea吗?
提前致谢。
S.
您需要 cross join
您的查询结果 calender
table。像这样
WITH t
AS (SELECT Row_number()
OVER (
ORDER BY Q2.FUNCTIONAL_LOCATION) AS Rowy,
Q1.FACT_MEASUREMENT_KEY,
CONVERT(VARCHAR(255), Q1.Doc_Time, 102) AS TIME
FROM dbo.DIM_PROJECT_TECH_OBJ Q2
INNER JOIN dbo.FACT_MEASUREMENT Q1
ON Q1.PROJECT_TECH_OBJ_KEY = Q2.PROJECT_TECH_OBJ_KEY
WHERE Q1.Measurement_Position = 'XXX'),
result
AS (SELECT t.*,
tprev.time
FROM t
LEFT JOIN t tprev
ON tprev.rowy = t.rowy - 1),
date_cook
AS (SELECT FUNTIONAL_LOC,
c.dates,
PRE_DATUM,
PRE_CODE
FROM result r
CROSS JOIN calender c
WHERE c.dates BETWEEN '2015-07-01' AND '2015-07-10')
SELECT dc.FUNTIONAL_LOC,
dc.dates AS DATUM,
Isnull(r.code, '') AS code,
dc.PRE_DATUM,
dc.PRE_CODE
FROM date_cook dc
LEFT OUTER JOIN result r
ON dc.FUNTIONAL_LOC= r.FUNTIONAL_LOC
AND dc.dates = r.DATUM
AND dc.PRE_DATUM = r.PRE_DATUM
AND dc.PRE_CODE = r.PRE_CODE
我通过创建 LEFT JOIN(日历记录到结果记录)进行了管理:在这种情况下,我避免了通过 CROSS 连接获得的笛卡尔积和所有重复项。
对于 PRE-CODE,我正在考虑对结果使用自连接 table:
WITH t as (
SELECT ROW_NUMBER() OVER (ORDER BY Q2.FUNCTIONAL_LOCATION) AS Rowy,
Q1.FACT_MEASUREMENT_KEY,
CONVERT(VARCHAR(255), Q1.Doc_Time, 102) AS TIME
FROM dbo.DIM_PROJECT_TECH_OBJ Q2 INNER JOIN
dbo.FACT_MEASUREMENT Q1
ON Q1.PROJECT_TECH_OBJ_KEY = Q2.PROJECT_TECH_OBJ_KEY
WHERE Q1.Measurement_Position = 'XXX'
)
select t.*, tprev.time
from t left join
t tprev
on tprev.rowy = t.rowy - 1;
您可以尝试以下步骤:
- 将此中间结果和 "calendar" table 定义为
WITH
语句的链
- 执行 "calendar" table 的
LEFT JOIN
和上面定义的中间结果(某些 DB 需要指定 LEFT OUTER JOIN
)
- 对上述两个步骤的结果再次执行行编号连接技术
前两步示例:
WITH t as ( ... ),
t2 as ( select t.*, tprev.time
from t left join
t tprev
on tprev.rowy = t.rowy - 1 ),
cal as ( ... )
SELECT *
FROM cal
LEFT JOIN t2
ON cal.DATUM = t2.DATUM;
请注意:
- 你原来问题的中间结果现在定义为
t2
- 在您模拟的最终结果中,您不能将 DATUM 的值保留为来自问题中报告的原始中间结果,因为缺少值,我想您确实想要显示所有日历取而代之的是
- 可以通过执行与您在原始问题中说明的相同的技术来获得上述步骤的第三点。
- 您需要在最终结果中指定顺序。
希望对您有所帮助!
我收到了一个 SelfJoin 查询
;WITH t as
(
SELECT
ROW_NUMBER() OVER (ORDER BY dbo.DIM_PROJECT_TECH_OBJ.FUNCTIONAL_LOCATION,DATEADD(ms, DATEDIFF(ms, '00:00:00', CONVERT(VARCHAR,REPLACE(dbo.FACT_MEASUREMENT.Doc_Time,'24:00:00','23:59:59'),102)), CONVERT(DATETIME, dbo.DIM_TIME_USAGE.DATE)) ASC) AS Rowy,
dbo.FACT_MEASUREMENT.FACT_MEASUREMENT_KEY,
dbo.FACT_MEASUREMENT.Doc_Number,
dbo.FACT_MEASUREMENT.Created_By,
dbo.FACT_MEASUREMENT.Text,
dbo.FACT_MEASUREMENT.Doc_Time,
dbo.FACT_MEASUREMENT.Date_Loaded,
dbo.DIM_VC_MEASURE.VALUATION_CODE_AND_DESC,
dbo.DIM_TIME_USAGE.DATE,
dbo.DIM_PROJECT_TECH_OBJ.FUNCTIONAL_LOCATION,
dbo.DIM_VC_MEASURE.VALUATION_CODE,
CONVERT(VARCHAR,REPLACE(dbo.FACT_MEASUREMENT.Doc_Time,'24:00:00','23:59:59'),102) AS TIME,
DATEADD(ms, DATEDIFF(ms, '00:00:00', CONVERT(VARCHAR,REPLACE(dbo.FACT_MEASUREMENT.Doc_Time,'24:00:00','23:59:59'),102)), CONVERT(DATETIME, dbo.DIM_TIME_USAGE.DATE)) AS DATUM
FROM
dbo.DIM_PROJECT_TECH_OBJ INNER JOIN dbo.FACT_MEASUREMENT ON (dbo.FACT_MEASUREMENT.PROJECT_TECH_OBJ_KEY=dbo.DIM_PROJECT_TECH_OBJ.PROJECT_TECH_OBJ_KEY)
INNER JOIN dbo.DIM_TIME_USAGE ON (dbo.FACT_MEASUREMENT.TIME_KEY=dbo.DIM_TIME_USAGE.TIME_KEY)
INNER JOIN dbo.DIM_VC_MEASURE ON (dbo.DIM_VC_MEASURE.VALUATION_CODE_KEY=dbo.FACT_MEASUREMENT.VALUATION_CODE_KEY)
WHERE
dbo.FACT_MEASUREMENT.Measurement_Position = 'AVAILABILITY'
AND
dbo.DIM_PROJECT_TECH_OBJ.FUNCTIONAL_LOCATION IN ('XXX','YYY','ZZZ')
)
select t.*, tprev.DATUM AS PRE_DATUM, tprev.VALUATION_CODE AS PRE_CODE, DATEDIFF (minute,tprev.DATUM, t.DATUM) AS DELTA_MIN
from t join
t tprev
on tprev.rowy = t.rowy - 1 AND tprev.FUNCTIONAL_LOCATION = t.FUNCTIONAL_LOCATION ;
这将return一组字段
FUNTIONAL LOC DATUM CODE PRE_DATUM PRE_CODE (-> Other fields)
XXX 01/07/2015 A 06/06/2015 Y
XXX 05/07/2015 B 01/07/2015 A
XXX 10/07/2015 C 05/07/2015 B
YYY 03/07/2015 B 15/06/2015 K
YYY 09/07/2015 C 03/07/2015 B
YYY 15/07/2015 A 09/07/2015 C
现在我想创建一个带有日历(从 01/07 到 10/07 的图像)日期的外部连接并获得类似的东西:
FUNTIONAL LOC DATUM CODE PRE_DATUM PRE_CODE
XXX 01/07/2015 A 06/06/2015 Y
XXX 02/07/2015 06/06/2015 Y
XXX 03/07/2015 06/06/2015 Y
XXX 04/07/2015 06/06/2015 Y
XXX 05/07/2015 B 01/07/2015 A
XXX 06/07/2015 01/07/2015 A
XXX 07/07/2015 01/07/2015 A
XXX 08/07/2015 01/07/2015 A
XXX 09/07/2015 01/07/2015 A
XXX 10/07/2015 C 05/07/2015 B
YYY 01/07/2015 15/06/2015 K
YYY 02/07/2015 15/06/2015 K
YYY 03/07/2015 B 15/06/2015 K
YYY 09/07/2015 C 03/07/2015 B
YYY 10/07/2015 03/07/2015 B
基本上当在日历数据上找不到代码时使用上一个。
有suggestion/idea吗? 提前致谢。
S.
您需要 cross join
您的查询结果 calender
table。像这样
WITH t
AS (SELECT Row_number()
OVER (
ORDER BY Q2.FUNCTIONAL_LOCATION) AS Rowy,
Q1.FACT_MEASUREMENT_KEY,
CONVERT(VARCHAR(255), Q1.Doc_Time, 102) AS TIME
FROM dbo.DIM_PROJECT_TECH_OBJ Q2
INNER JOIN dbo.FACT_MEASUREMENT Q1
ON Q1.PROJECT_TECH_OBJ_KEY = Q2.PROJECT_TECH_OBJ_KEY
WHERE Q1.Measurement_Position = 'XXX'),
result
AS (SELECT t.*,
tprev.time
FROM t
LEFT JOIN t tprev
ON tprev.rowy = t.rowy - 1),
date_cook
AS (SELECT FUNTIONAL_LOC,
c.dates,
PRE_DATUM,
PRE_CODE
FROM result r
CROSS JOIN calender c
WHERE c.dates BETWEEN '2015-07-01' AND '2015-07-10')
SELECT dc.FUNTIONAL_LOC,
dc.dates AS DATUM,
Isnull(r.code, '') AS code,
dc.PRE_DATUM,
dc.PRE_CODE
FROM date_cook dc
LEFT OUTER JOIN result r
ON dc.FUNTIONAL_LOC= r.FUNTIONAL_LOC
AND dc.dates = r.DATUM
AND dc.PRE_DATUM = r.PRE_DATUM
AND dc.PRE_CODE = r.PRE_CODE
我通过创建 LEFT JOIN(日历记录到结果记录)进行了管理:在这种情况下,我避免了通过 CROSS 连接获得的笛卡尔积和所有重复项。 对于 PRE-CODE,我正在考虑对结果使用自连接 table:
WITH t as (
SELECT ROW_NUMBER() OVER (ORDER BY Q2.FUNCTIONAL_LOCATION) AS Rowy,
Q1.FACT_MEASUREMENT_KEY,
CONVERT(VARCHAR(255), Q1.Doc_Time, 102) AS TIME
FROM dbo.DIM_PROJECT_TECH_OBJ Q2 INNER JOIN
dbo.FACT_MEASUREMENT Q1
ON Q1.PROJECT_TECH_OBJ_KEY = Q2.PROJECT_TECH_OBJ_KEY
WHERE Q1.Measurement_Position = 'XXX'
)
select t.*, tprev.time
from t left join
t tprev
on tprev.rowy = t.rowy - 1;
您可以尝试以下步骤:
- 将此中间结果和 "calendar" table 定义为
WITH
语句的链 - 执行 "calendar" table 的
LEFT JOIN
和上面定义的中间结果(某些 DB 需要指定LEFT OUTER JOIN
) - 对上述两个步骤的结果再次执行行编号连接技术
前两步示例:
WITH t as ( ... ),
t2 as ( select t.*, tprev.time
from t left join
t tprev
on tprev.rowy = t.rowy - 1 ),
cal as ( ... )
SELECT *
FROM cal
LEFT JOIN t2
ON cal.DATUM = t2.DATUM;
请注意:
- 你原来问题的中间结果现在定义为
t2
- 在您模拟的最终结果中,您不能将 DATUM 的值保留为来自问题中报告的原始中间结果,因为缺少值,我想您确实想要显示所有日历取而代之的是
- 可以通过执行与您在原始问题中说明的相同的技术来获得上述步骤的第三点。
- 您需要在最终结果中指定顺序。
希望对您有所帮助!