我有超过5个国家的计算用户频率表(~40M):
DB: Oracle 11g
Minimal Schema: ID - Integer, Freq - Varchar
所以基本上,我试图根据每天动态提取订阅者。
Frequency Chart (May differ based for each countries):
7X - Everyday
5X - All weekdays
3X - Monday, Wednesday, Friday
2X - Tuesday, Thursday
1X - Wednesday
我编写了以下查询,每天会给出不同的列表(修改 ^以便更好地理解):
SELECT ID
FROM (
WITH CONST AS (
SELECT TO_CHAR(TRUNC(SYSDATE + 5 / 8), 'D') TODAY_
FROM DUAL
)
SELECT C.ID
,FREQ
,CASE
WHEN FREQ = '7X'
THEN TODAY_
WHEN FREQ = '5X'
AND TODAY_ NOT IN (
1
,7
)
THEN TODAY_
WHEN FREQ = '3X'
AND TODAY_ IN (
2
,4
,6
)
THEN TODAY_
WHEN FREQ = '2X'
AND TODAY_ IN (
3
,5
)
THEN TODAY_
WHEN FREQ = '1X'
AND TODAY_ = 4
THEN TODAY_
END AS TARGET_
FROM CONST
,CONTACT C
INNER JOIN ENGAGEMENT ENG ON C.ID = ENG.ID
AND C.COUNTRY_ID = '1'
)
WHERE TARGET_ IS NOT NULL
我有两个问题
1)在CONST
子查询中,我试图将PST转换为ICT。还有其他更好的方法来转换oracle中的时区
2)因为我根据每个国家/地区有不同的查询。每次查询都需要大约5-10分钟才能获取结果。我不确定查询的优化程度。
答案 0 :(得分:0)
您不应该依赖TO_CHAR(..., 'D')
,因为结果取决于NLS_TERRITORY
的当前设置,这些设置在每个会话中可能不同。 NLS_DATE_LANGUAGE
也可以不同,因此最好明确指定它。
ICT
不是有效的时区名称,我假设您的意思是“亚洲/曼谷”。 PST
也不明确。
这个应该有效:
WITH t AS
(SELECT
TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'Asia/Bangkok', 'fmDay', 'NLS_DATE_LANGUAGE = american' ) AS TODAY
FROM dual)
SELECT ID
FROM CONTACT C
INNER JOIN ENGAGEMENT ENG ON C.ID = ENG.ID
CROSS JOIN t
WHERE C.COUNTRY_ID = 1
AND (
(FREQ = '7X')
OR (FREQ = '5X' AND TODAY NOT IN ('Saturday','Sunday') )
OR (FREQ = '3X' AND TODAY IN ('Monday', 'Wednesday', 'Friday') )
OR (FREQ = '2X' AND TODAY IN ('Tuesday', 'Thursday') )
OR (FREQ = '1X' AND TODAY IN ('Wednesday') )
);