我想选择数据库表的最新条目,该表包含具有相同产品编号(但日期不同)的多行。
在这种特殊情况下,我希望按TKP_NOISE_MOTOR_RESULTS
表过滤PRODUCT_NUMBER
表,该表在表中至少出现五次,而在该子集中,我想要检索最近的行{ {1}}每个prdocut编号
我设法创建了这样一个查询,但有三个子查询T1,T2,T3。我感觉只有两个表可以完成,不需要内连接。但是创建它需要花费很多时间,因为很难将脚本从MySQL转换为Oracle。
是否可以优化以下查询,因此需要更少的子查询?
SAVEDATE
答案 0 :(得分:2)
如果您只想要产品编号和日期,可以简化当前的方法;如你所怀疑的那样,你需要多次访问该表,并且可以用IN
子句替换连接:
SELECT PRODUCT_NUMBER, MAX(SAVEDATE)
FROM TKP_NOISE_MOTOR_RESULTS
WHERE PRODUCT_NUMBER IN (
SELECT PRODUCT_NUMBER
FROM TKP_NOISE_MOTOR_RESULTS
GROUP BY PRODUCT_NUMBER
HAVING COUNT(*)>5
)
GROUP BY PRODUCT_NUMBER;
但是如果你有其他专栏,那么你需要让它更复杂。
您可以使用analytic functions来防止必须多次敲击表格或进行任何加入:
SELECT PRODUCT_NUMBER, SAVEDATE --, other columns
FROM (
SELECT T.*,
ROW_NUMBER() OVER (PARTITION BY T.PRODUCT_NUMBER
ORDER BY T.SAVEDATE DESC) AS RN,
COUNT(*) OVER (PARTITION BY T.PRODUCT_NUMBER) AS CNT
FROM TKP_NOISE_MOTOR_RESULTS T
WHERE T.SAVEDATE BETWEEN DATE '2014-08-27' AND DATE '2014-08-28'
)
WHERE CNT > 5
AND RN = 1;
内部查询从基表中获取所有列,并根据分析函数添加伪列。 ROW_NUMBER()
为特定产品的每一行指定一个值,最新日期为数字1(通过ORDER BY ... DESC
)。您还可以考虑RANK()
或DENSE_RANK()
,特别是如果您可能有关系,并希望在出现平局时显示所有行。 COUNT(*)
计算每种产品的行数。
外部查询然后将其过滤为仅包含计数大于5的产品;并且也只是排在第一位,这是最新的。
SQL Fiddle使用您的原始查询,并使用相同的数据。
我也转而使用日期文字;您应该至少使用TO_DATE
使用显式格式掩码而不是依赖会话NLS设置。另请注意,BETWEEN
包含在内,所以这个(和你原来的)会在28日午夜开始;你可能想用:
WHERE T.SAVEDATE >= DATE '2014-08-27'
AND T.SAVEDATE < DATE '2014-08-28'
..或者如果您尝试包括这两天的所有记录,那么< DATE '2014-08-29'
。我认为他们有时间,否则同一日期的五个记录看起来是一样的,你需要一些其他的方式来决定哪个是最新的#。
答案 1 :(得分:2)
除非使用相当旧的Oracle版本,否则您可以使用COUNT()
和ROW_NUMBER()
的分析形式来获得我认为的结果。试试这个:
SELECT
*
FROM (
SELECT
TNMR.*
, COUNT(*) OVER (PARTITION BY TNMR.PRODUCT_NUMBER) AS CN
, ROW_NUMBER() OVER (PARTITION BY TNMR.PRODUCT_NUMBER
ORDER BY TNMR.SAVEDATE DESC) AS RN
FROM messfeld.TKP_NOISE_MOTOR_RESULTS TNMR
) T1
WHERE T1.CN >= 5 AND T1.RN = 1
AND T1.SAVEDATE BETWEEN '27-AUG-14' AND '28-AUG-14'
;
但是我真的不推荐dd-mmm-yy作为日期文字,我从不使用BETWEEN
作为日期范围,而是使用它代替:
AND T1.SAVEDATE >= to_date('27-08-2014','dd-mmm-yyyy')
AND T1.SAVEDATE < to_date('28-08-2014','dd-mmm-yyyy') + 1 -- 1 day added
FOOTNOTE &#34;选择*&#34;仅用于方便,上面仅用于缩写和/或因为细节未知。请完整说明选择条款。
答案 2 :(得分:1)
您似乎正在搜索所有
的产品其中你想要在该日期范围内找到最新记录。
因此,选择所有包含5条以上记录的产品(如您所做),并使用案例构造确定日期范围内的最新保存日期。
select *
from messfeld.tkp_noise_motor_results
where (product_number, savedate) in
(
select
product_number,
max(case when to_char(savedate, 'dd-mm-yyyy') in ('27-08-2014', '28-08-2014') then savedate end)
from messfeld.tkp_noise_motor_results
group by product_number
having count(*) > 5
-- the next line is not really needed. Use it if you find it more readable
and max(case when to_char(savedate, 'dd-mm-yyyy') in ('27-08-2014', '28-08-2014') then savedate end) is not null
);