2013-12-11 57 views
2

我有一個視圖名稱RULE_READOUT_VIEW有varchar列名爲'READOUTTYPE'和'CUSTOMERNUMBER'。Oracle SQL奇怪的問題與我下面的查詢

當我運行下面的計數查詢時,我只得到一行作爲輸出。

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

但是,如果運行這個其他查詢我得到不同的結果,這一次計數是11行是什麼是預期的結果。

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

我不知道爲什麼第一個查詢不工作的地方只有當我強迫的專欄中,我得到正確的答案一個TO_CHAR。我尋找答案,但找不到滿意的東西。有人可以解釋爲什麼這種行爲?

我跑到下面的查詢,以檢查各的長度和每一行太

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

我得到了11行作爲輸出,以及所有列的長度有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 | TABLE ACCESS BY INDEX ROWID | REF_METER_READ_OUT_TYPE | 1 | 7 | 1 |
| 20 | INDEX UNIQUE SCAN | 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 | INDEX快速全面掃描| PK_METERREADTYPE | 1 | 7 | 1 |
| 15 | INDEX快速全面掃描| UQ_REF_METER_READ_OUT_TY_NAME | 1 | 7 | 1 |

+0

確保您的readouttype列是乾淨的,即沒有帶空白的條目。 – Mat

+0

我檢查了列值。我無法在之前或之後看到任何附加的空格。另外如果我運行下面的查詢我也得到11行SELECT count(1)FROM RULE_READOUT_VIEW其中READOUTTYPE像'5'和CUSTOMERNUMBER ='NSMPF'。這個問題似乎只有當我單獨使用相等運算符時纔會出現。 – thiyaga

+0

你是如何檢查的?你的「工作」查詢表明你的讀出列不僅包含'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 '和CUSTOMERNUMBER ='NSMPF';沒有選擇行 – thiyaga

+0

您的Idea2似乎產生了正確的結果。如果我在創建的臨時表上運行查詢,那麼我會得到正確的結果。但是,我仍然不明白它是如何工作在從視圖創建的表上,但對視圖本身無效? – thiyaga

+0

@thiyaga我認爲數據本身是好的,而且你遇到了一些描述的Oracle錯誤,這是由不同查詢引起的計劃差異所觸發/隱藏的。 –

1

我懷疑REF_METER_READ_OUT_TYPE.NAME上可能有損壞的索引,並且查詢結果之間的差異是由是否使用索引的差異來解釋的。

嘗試刪除並重新創建索引(不重建,因爲這可能會保留任何損壞)。

+0

我丟棄並重新創建索引。仍然是同樣的問題。 – thiyaga

+0

你可以發佈兩個查詢的執行計劃嗎? –

+0

由於我不能發佈完整的計劃,因爲它超過了允許的大小,我已經使用readoutype列的計劃片段更新了我的查詢。 – thiyaga