2013-12-11 2 views
2

'READOUTTYPE'및 'CUSTOMERNUMBER'라는 varchar 열이있는 뷰 이름은 RULE_READOUT_VIEW입니다.아래 쿼리에 오라클 SQL 이상한 문제가 발생했습니다.

다음 카운트 쿼리를 실행하면 한 행만 출력됩니다.

SELECT count(1) FROM RULE_READOUT_VIEW 
WHERE READOUTTYPE = '5' AND CUSTOMERNUMBER = 'NSMPF'; 

그러나이 다른 쿼리를 실행하면 결과가 달라지고이 시간 수는 예상되는 결과 인 11 행입니다. 제가 정확한 답변을 얻을 컬럼에 TO_CHAR를 강제하는 경우에만 경우로 첫 번째 쿼리가 작동하지 않는 이유

SELECT count(1) FROM RULE_READOUT_VIEW 
WHERE to_char(READOUTTYPE) = '5' AND CUSTOMERNUMBER = 'NSMPF'; 

나는 확실하지 않다. 나는 해답을 찾았지만 만족스런 것을 찾지 못했다. 어떤 사람이 왜이 행동을 설명 할 수 있습니까?

나는 각각의 길이와 내가 출력으로 11 개 행을 가지고 너무

SELECT READOUTTYPE, TO_CHAR(READOUTTYPE), LENGTH(READOUTTYPE), LENGTHB(READOUTTYPE) FROM teoss.RULE_READOUT_VIEW WHERE to_char(READOUTTYPE) = '5' and CUSTOMERNUMBER = 'NSMPF'; 

모든 행과 모든 열이 길이 그래서 1

5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 
5 5 1 1 

를 확인하기 위해 아래 쿼리를 실행 열에는 추가 공백도 없습니다.

보기 DDL은 :

SELECT --ro.creation_date, 
ro.POINT_OF_TIME_DAY      AS pointOfReadoutDay, 
ro.POINT_OF_TIME_HOUR      AS pointOfReadoutHour, 
ro.POINT_OF_TIME_MINUTE     AS pointOfReadoutMinute, 
rot.NAME         AS readoutType, 
cp.IDENTIFICATION       AS customerNumber, 
mp.METER_POINT_NUMBER      AS meterPointNumber, 
ro.ORDER_REFERENCE      AS readoutOrderNumber, 
mtrefstat.NAME       AS meterStatus, 
mt.ADDRESS        AS address, 
mt.SERIAL_NUMBER       AS serialNumber, 
mt.UPPER_SERIAL_NUMBER     AS upperSerialNumber, 
servrefstat.NAME       AS serverStatus, 
mus.MAC         AS hostname, 
mserv.IP_ADDRESS       AS ipAddress , 
mt.device_id        AS deviceID, 
GET_ACCESSCONNECTION_TYPE(mus.device_id) AS ACCESSCONNECTIONTYPE, 
FUNC_LIST_OBIS_NAME(ro.order_read_out_id) AS refObisList, 
mt.METER_NUMBER       AS meterNumber 
FROM ORDER_READ_OUT ro, 
REF_METER_READ_OUT_TYPE rot, 
COMPANY cp, 
METER_POINT mp, 
METER mt, 
MAP_DEVICE_STATUS mtstat, 
REF_STATUS mtrefstat, 
DEVICE servdev, 
MUS mus, 
METERING_SERVER mserv, 
MAP_DEVICE_STATUS servstat, 
REF_STATUS servrefstat, 
MAP_ORD_RD_OUT_CNTRCT_MT_PT mocm, 
MAP_CONTRACT_METER_POINT mcm, 
CONTRACT co 
WHERE -- order readout relation has to be valid 
mocm .ORDER_READ_OUT_ID   = ro.ORDER_READ_OUT_ID 
AND ro.REF_METER_READ_OUT_TYPE_ID = rot.REF_METER_READ_OUT_TYPE_ID 
AND ro.ACTIVATION_DATE   <= SYSTIMESTAMP 
AND (ro.DEACTIVATION_DATE  IS NULL 
OR ro.DEACTIVATION_DATE   > SYSTIMESTAMP) 
-- contract relation has to be valid ... 
AND mocm.MAP_CONTRACT_METER_POINT_ID = mcm.MAP_CONTRACT_METER_POINT_ID 
AND mcm.CONTRACT_ID     = co.CONTRACT_ID 
AND co.COMPANY_ID     = cp.COMPANY_ID 
AND ((co.BEGIN      IS NULL 
AND mcm.BEGIN      <= SYSTIMESTAMP) 
OR (co.BEGIN      <= SYSTIMESTAMP 
AND mcm.BEGIN      <= SYSTIMESTAMP 
AND mcm.begin      >= co.begin)) 
AND (mcm.end      IS NULL 
OR mcm.end       >= SYSTIMESTAMP) 
AND ((co.END      IS NULL) 
OR (co.END       >= SYSTIMESTAMP 
AND ((mcm.end      IS NULL) 
OR (mcm.end       <= co.end)))) 
-- meter point relation has to be valid ... 
AND mcm.METER_POINT_ID = mp.METER_POINT_ID 
AND mp.METER_POINT_ID = mt.METER_POINT_ID 
AND mt.DEVICE_ID   = mtstat.DEVICE_ID 
AND mtstat.REF_STATUS_ID = mtrefstat.REF_STATUS_ID 
AND (mtrefstat.name  = 'active' 
OR mtrefstat.name  = 'toBeRemoved') 
AND mtstat.STATUS_DATE = 
(SELECT MAX(mds.status_date) 
FROM Map_device_status mds 
WHERE mds.device_id = mtstat.DEVICE_ID 
) 
-- mus/metering-server relation has to be valid 
AND servdev.DEVICE_ID = 
(SELECT FUNC_FIND_SERVER_DEV_ID(mt.DEVICE_ID) FROM DUAL 
) 
AND servdev.DEVICE_ID  = mus.DEVICE_ID(+) 
AND servdev.DEVICE_ID  = mserv.DEVICE_ID(+) 
AND servdev.DEVICE_ID  = servstat.DEVICE_ID 
AND servstat.REF_STATUS_ID = servrefstat.REF_STATUS_ID 
AND (servrefstat.name  = 'active' 
OR servrefstat.name  = 'toBeRemoved') 
AND servstat.STATUS_DATE = 
(SELECT MAX(mds.status_date) 
FROM Map_device_status mds 
WHERE mds.device_id = servstat.DEVICE_ID 
) 
AND ro.CREATION_DATE = 
(SELECT MAX(t9.CREATION_DATE) 
FROM ORDER_READ_OUT t9 
WHERE t9.point_of_time_day  = ro.point_of_time_day 
AND t9.point_of_time_hour   = ro.point_of_time_hour 
AND t9.point_of_time_minute  = ro.point_of_time_minute 
AND t9.ref_meter_read_out_type_id = ro.ref_meter_read_out_type_id 
AND t9.ORDER_READ_OUT_ID   IN 
(SELECT t5.ORDER_READ_OUT_ID 
FROM map_ord_rd_out_cntrct_mt_pt t5 
WHERE t5.MAP_CONTRACT_METER_POINT_ID = mcm.MAP_CONTRACT_METER_POINT_ID 
)); 

계획 니펫을 : explain plan for SELECT count(1) FROM RULE_READOUT_VIEW WHERE READOUTTYPE = '5' AND CUSTOMERNUMBER = 'NSMPF';

| 19 | INDEX ROWID에 의한 테이블 액세스 | REF_METER_READ_OUT_TYPE | 1 | 7 | 1 |
| 20 | INDEX 고유 스캔 | UQ_REF_METER_READ_OUT_TY_NAME | 1 | | 0

explain plan for SELECT count(1) FROM RULE_READOUT_VIEW WHERE to_char(READOUTTYPE) = '5' AND CUSTOMERNUMBER = 'NSMPF'; 

| 14 | 빠른 검색 | PK_METERREADTYPE | 1 | 7 | 1 |
| 15 | 빠른 검색 | UQ_REF_METER_READ_OUT_TY_NAME | 1 | 7 | 1 |

+0

귀하의 readouttype 열이 깨끗한 지, 즉 공백이있는 항목이 없는지 확인하십시오. – Mat

+0

열 값을 확인했습니다. 전후에 추가 공백이 보이지 않습니다. 또한 내가 아래의 쿼리를 실행하는 경우에도 나는 11 행을 얻는다. (5) 'CUSTOMERNUMBER ='NSMPF '와 같은 READOUTTYPE과 같은 RULE_READOUT_VIEW에서 SELECT count (1)를 얻는다. 문제는 내가 평등 연산자 만 사용하는 경우 인 것 같습니다. – thiyaga

+0

어떻게 확인 했습니까? 두 "작업 중"쿼리는 사용자의 readout 열에 '5'만 포함되지 않고 다른 공백과 같은 내용이 있음을 나타냅니다. – Mat

답변

1

아이디어 1 :이 쿼리를 실행하면

, 당신은 다시 문제가있는 행을 얻어야한다 : -

SELECT READOUTTYPE, TO_CHAR(READOUTTYPE), LENGTH(READOUTTYPE) 
FROM RULE_READOUT_VIEW 
WHERE to_char(READOUTTPYE) = '5' 
AND READOUTTYPE != '5' 
AND CUSTOMERNUMBER = 'NSMPF'; 

아마도 그것이 명확하게 있는지 확인하기 위해이 쿼리의 결과와 질문을 업데이트 누구에게나.

아이디어 2 :

이 시도 :

CREATE TABLE TEMP_RULE_READOUT AS 
SELECT * FROM RULE_READOUT_VIEW 
WHERE CUSTOMERNUMBER = 'NSMPF'; 

SELECT count(1) FROM TEMP_RULE_READOUT 
WHERE READOUTTYPE = '5' AND CUSTOMERNUMBER = 'NSMPF'; 

SELECT count(1) FROM RULE_READOUT_VIEW 
WHERE to_char(READOUTTYPE) = '5' AND CUSTOMERNUMBER = 'NSMPF'; 

보는 것은 흥미로운 일이 될 것이다는 데이터가 테이블로 구체화 될 때이 제대로 여부를 작동합니다.

+0

당신이 물어 본 쿼리를 실행했습니다. 다음 쿼리에 의해 반환 된 행이 없습니다. SQL> SELECT READOUTTYPE, TO_CHAR (READOUTTYPE), LENGTH (READOUTTYPE), LENGTH (TO_CHAR (READOUTTYPE)) FROM teoss.RULE_READOUT_VIEW where TO_CHAR (READOUTTYPE) = '5'AND READOUTTYPE! = '5 'AND CUSTOMERNUMBER ='NSMPF '; 선택된 행이 없습니다 – thiyaga

+0

Idea2가 올바른 결과를 생성하는 것 같습니다. 내가 만든 임시 테이블에서 쿼리를 실행하면 올바른 결과를 얻습니다. 그러나 나는 여전히보기에서 생성 된 테이블에서 작동하지만 뷰 자체에서 작동하지 않습니다. – thiyaga

+0

@thiyaga 나는 데이터 자체가 괜찮다고 생각하고, 다른 쿼리로 인한 계획의 차이에 의해 숨겨 지거나 숨겨진 몇 가지 설명의 Oracle 버그로 실행되고 있다고 생각합니다. –

1

REF_METER_READ_OUT_TYPE.NAME에 손상된 인덱스가있는 것으로 의심되며 쿼리 결과의 차이는 인덱스의 사용 여부에 따라 설명됩니다.

색인을 삭제하고 다시 작성해보십시오 (다시 작성하지 않으면 손상이 없어 질 수 있음).

+0

색인을 삭제하고 다시 만들었습니다. 여전히 같은 문제입니다. – thiyaga

+0

두 쿼리에 대한 실행 계획을 게시 할 수 있습니까? –

+0

허용 된 크기를 초과하여 완전한 계획을 게시 할 수 없기 때문에 readoutype 열을 사용하는 계획 스 니펫으로 내 쿼리를 업데이트했습니다. – thiyaga

관련 문제