我有下表
R_ID DATE Col_A Col_B Col_C
158 20161008 01 99 99
158 20161012 01 01 99
158 20161019 01 02 10
158 20161022 99 01 10
160 20161006 01 99 01
160 20161011 99 01 99
160 20161017 99 01 10
167 20161013 99 01 01
167 20161016 99 02 99
167 20161020 02 01 10
我想选择这样我得到以下结果
R_ID DATE Col_A Col_B Col_C
158 20161008 01 01 99 - Entry record
158 20161022 99 01 10 - Exit Record
160 20161006 01 99 01 - Entry record
160 20161017 99 01 10 - Exit Record
167 20161013 99 01 01 - Entry record
167 20161020 02 01 10 - Exit Record
For each R_ID:
When Col_A or Col_B = '01' and Col_C <>'10' - **It is an entry record**
When Col_C = '10' - **It is an exit record**
这里的逻辑是
1. Select the earliest entry record
**and**
2. Select the latest exit record for each R_ID
我正在考虑使用下面的联盟...
Select * from tbl1 T
where
T.Col_C = '10' and
T.DATE = (select max(T2.DATE) from tbl1 T2
where
T2.Col_C = '10' and
T3.R_ID = T.R_ID
)
union
Select * from tbl1 K
where
(K.Col_A = '01' or K.Col_B = '01') and
K.Col_C <> '10' and
K.DATE = (select min(K2.DATE) from tbl1 K2 where
(K2.Col_A = '01' or K2.Col_B = '01') and
K2.Col_C <> '10' and
K2.R_ID = K.R_ID
)
但是像我在同一个表上使用自联接一样使用联合返回给我一个垃圾数据。
这可以通过连接来实现吗?
答案 0 :(得分:1)
可能是一种更简单的方法......但我认为这可以通过一些易于遵循/维护的步骤使用CTE(常见的表格表达式)
这将生成每个R_ID的最小日期的数据集和每个R_ID的最大数据集,然后将这些集合连接到基集并将结果联合起来以获得所需的结果。由于我们使用了一个联合,我们需要将它全部包装在一个选择中以获得正确的顺序。
m v
我将&#34; date&#34;的名称更改为mdate,以避免因为它是关键字而无法转义列名。我也没有包括你所有的限制标准。
答案 1 :(得分:1)
此解决方案有一个子查询,可以在两个方向上对所有DATE值进行排名。子查询在UNION ALL中用于获取所需的输出。
with cte as (
select R_ID
, DATE
, COL_A
, COL_B
, COL_C
, rank() over (partition by R_ID order by DATE asc, COL_A asc ) as entry_rnk
, rank() over (partition by R_ID order by DATE desc, COL_A asc ) as exit_rnk
from TBL1
)
select R_ID
, DATE
, COL_A
, COL_B
, COL_C
, 'Entry record'
from cte
where entry_rnk = 1
union all
select R_ID
, DATE
, COL_A
, COL_B
, COL_C
, 'Exit record'
from cte
where exit_rnk = 1
order by 1, 5
/
我说实话:我忽略了发布的WHERE子句中的其他过滤器,因为没有解释他们应用的规则。也许您需要将它们包含在WITH子句和/或UNION&#39; d查询
中答案 2 :(得分:0)
问题在于,您可以获得与日期过滤器匹配的多行,并匹配一些COL_A,B,C条件,但其中说K.COL_C&lt;&gt; 10和K2.COL_C&lt;&gt; 10但K.COL_C可能与K2.COL_C匹配,也可能不匹配 或T.COL_C = 10且T2.COL_C = 10但可能T.COL_A和T.COL_B不匹配T2.COL_A或T2.COL_B。
这是一个不使用联合的查询。如果您考虑将2 where子句更改为两者的OR,则它在结构上与您的union查询类似。它还添加了COL_A,COL_B和COL_C匹配。
Select
BASE_TABLE.*
from
tbl1 as BASE_TABLE,
( select K2.R_ID, min(K2.DATE) as MINDATE,
K2.COL_A, K2.COL_B, K2.COL_C
from tbl1 K2
where
(K2.Col_A = '01' or K2.Col_B = '01') and
K2.Col_C <> '10'
group by K2.R_ID, K2.COL_A, K2.COL_B, K2.COL_C )
AS ENTRY_FILTER ,
( select T2.R_ID, max(T2.DATE) as MAXDATE,
T2.COL_A,T2.COL_B, T2.COL_C
from tbl1 T2
where
T2.Col_C = '10'
group by T2.R_ID, T2.COL_A,T2.COL_B, T2.COL_C
)
AS EXIT_FILTER
where
( ENTRY_FILTER.R_ID = BASE_TABLE.R_ID
AND BASE_TABLE.DATE = ENTRY_FILTER.MINDATE
and BASE_TABLE.COL_A = ENTRY_FILTER.COL_A
and BASE_TABLE.COL_B = ENTRY_FILTER.COL_B
and BASE_TABLE.COL_C = ENTRY_FILTER.COL_C
)
or
(
EXIT_FILTER.R_ID = BASE_TABLE.R_ID;
AND BASE_TABLE.DATE = EXIT_FILTER.MAXDATE
AND BASE_TABLE.COL_A = EXIT_FILTER.COL_A
AND BASE_TABLE.COL_B = EXIT_FILTER.COL_B
AND BASE_TABLE.COL_C = EXIT_FILTER.COL_C
)