"end-of-file on communication channel" error with UNION of DISTINCT columns - sql

I'm cleaning up SQL code from a previous engineer (not a programmer).
One query UNIONs the results to 2 almost identical queries, with an exactly identical sub-query, and the original code has a lot of "where" clauses (in both queries) to filter the data.
I am trying to use "with" tables to filter the data first, and then do the sub-queries and the union.
I keep getting a generic "end-of-file on communication channel" error during the "Prepare" step, but when I remove the DISTINCT clause from the sub-queries, it works - but it doesn't give me the results I need.
Here is the code I've "reduced" to show the error:
with
FilteredData as
(
select
ST.part
, ST.order_No
, ST.induct_Date
, ST.complete_Date
from
Some_Table ST
where
(
ST.part is not null
and ST.order_No is not null
)
-- MUCH more filtering goes on here, to limit the number of records to look at
)
,
TempTable_01A as
(
select
FD.part
, count( DISTINCT FD.part ) Count_1 -- The DISTINCT needs to be removed for it to compile
, 0 Count_2
, 0 AvgLengthOpen
from
FilteredData FD
where
FD.induct_Date is not null
and ( FD.induct_Date >= to_date( '01-01-2013', 'MM-DD-YYYY' ) )
and ( FD.induct_Date < ( to_date( '01-31-2013', 'MM-DD-YYYY' ) + 1 ) )
group by
FD.part
)
,
TempTable_01B as
(
select
FD.part
, 0 Count_1
, count( DISTINCT FD.part ) Count_2 -- The DISTINCT needs to be removed for it to compile
, avg( FD.complete_Date - FD.induct_Date ) AvgLengthOpen
from
FilteredData FD
where
FD.complete_Date is not null
and ( FD.complete_Date >= to_date( '01-01-2013', 'MM-DD-YYYY' ) )
and ( FD.complete_Date < ( to_date( '01-31-2013', 'MM-DD-YYYY' ) + 1 ) )
group by
FD.part
)
,
UnionTable as
(
select
TT_A.part
, TT_A.Count_1
, TT_A.Count_2
, TT_A.AvgLengthOpen
from
TempTable_01A TT_A
union
select
TT_B.part
, TT_B.Count_1
, TT_B.Count_2
, TT_B.AvgLengthOpen
from
TempTable_01B TT_B
)
select
UT.part
, max( UT.Count_1 ) MaxCount_1
, max( UT.Count_2 ) MaxCount_2
, max( UT.AvgLengthOpen ) MaxAvgLengthOpen
from
UnionTable UT
group by
UT.part
order by
1
NOTE: I am using Oracle SQL, version 10.0.2.1697. I get this same error whether I'm using PLSQL Developer, or my Perl program.

Related

I want to reduce my SQL Query on big Query

I want to fetch data from bigQuery database but I get an error
=>The query is too large. The maximum query length is 256.000K characters, including comments and white space characters.
i will show a part of query which i repeated 21 times
WITH data AS
(
SELECT
IFNULL(department, 'UNKNOWN_DEPARTMENT') AS dept,
> 'C7s'
AS campus,
COUNTIF(task.taskRaised.raisedAt.milliSeconds BETWEEN 1542565800000 AND 1543170599999) AS taskCount_0,
COUNTIF(task.taskRaised.raisedAt.milliSeconds BETWEEN 1542565800000 AND 1543170599999
AND IF (task.deadline.currentEscalationLevel NOT IN
(
'ESC_ACKNOWLEDGEMENT'
)
, task.deadline.currentEscalationLevel, 'NOT_ESCALATED') NOT IN
(
'NOT_ESCALATED'
)
) AS escCount_0,
COUNTIF(task.taskRaised.raisedAt.milliSeconds BETWEEN 1541961000000 AND 1542565799999) AS taskCount_1,
COUNTIF(task.taskRaised.raisedAt.milliSeconds BETWEEN 1541961000000 AND 1542565799999
AND IF (task.deadline.currentEscalationLevel NOT IN
(
'ESC_ACKNOWLEDGEMENT'
)
, task.deadline.currentEscalationLevel, 'NOT_ESCALATED') NOT IN
(
'NOT_ESCALATED'
)
) AS escCount_1,
COUNTIF(task.taskRaised.raisedAt.milliSeconds BETWEEN 1541356200000 AND 1541960999999) AS taskCount_2,
COUNTIF(task.taskRaised.raisedAt.milliSeconds BETWEEN 1541356200000 AND 1541960999999
AND IF (task.deadline.currentEscalationLevel NOT IN
(
'ESC_ACKNOWLEDGEMENT'
)
, task.deadline.currentEscalationLevel, 'NOT_ESCALATED') NOT IN
(
'NOT_ESCALATED'
)
) AS escCount_2
FROM
> `nsimplbigquery.TaskManagement.C7s_*`
WHERE
_TABLE_SUFFIX IN
(
'2018_47_11',
'2018_45_11',
'2018_46_11'
)
AND IFNULL(department, 'UNKNOWN_DEPARTMENT') IN
(
'ENGG_AND_MAINT_DEPARTMENT',
'FNB_DEPARTMENT',
'TELECOM_DEPARTMENT',
'IT_DEPARTMENT',
'BILLING_AND_INSURANCE',
'HOUSEKEEPING_DEPARTMENT'
)
AND task.taskRaised.raisedAt.milliSeconds BETWEEN 1541356200000 AND 1543170599999
GROUP BY
dept
)
,
mainQuery AS
(
SELECT
dept,
campus,
SUM(taskCount_0) AS taskCount_0,
SUM(escCount_0) AS escCount_0,
CAST(SAFE_DIVIDE(SUM(escCount_0), SUM(taskCount_0)) * 10000 AS INT64) AS escPerc_0,
SUM(taskCount_1) AS taskCount_1,
SUM(escCount_1) AS escCount_1,
CAST(SAFE_DIVIDE(SUM(escCount_1), SUM(taskCount_1)) * 10000 AS INT64) AS escPerc_1,
SUM(taskCount_2) AS taskCount_2,
SUM(escCount_2) AS escCount_2,
CAST(SAFE_DIVIDE(SUM(escCount_2), SUM(taskCount_2)) * 10000 AS INT64) AS escPerc_2
FROM
data
GROUP BY
ROLLUP (campus, dept)
)
SELECT
dept,
campus,
taskCount_0,
escCount_0,
escPerc_0,
taskCount_1,
escCount_1,
escPerc_1,
taskCount_2,
escCount_2,
escPerc_2
FROM
mainQuery
WHERE
campus IS NOT NULL
ORDER BY
CASE
WHEN
dept IS NULL
THEN
1
ELSE
0
END
ASC, dept ASC, campus ASC;
This is the query which I repeat so many times so can due to I have so many ids Where C7s i changed with following ids
C7z,
C7u,
H0B,
IDp,
ITR,
C7i,
C7j,
C7k,
C7l,
C7m,
C7o,
C71,
C7t,
F6qZ,
C7w,
GIui,
Fs,
C70,
C7p,
C7r
if you see my explainantion i quote a line this nsimplbigquery.TaskManagement.C7s_*
so at next query the table names is changed
like
nsimplbigquery.TaskManagement.C7z_*
Instead of repeating your whole SELECT statement 21 times, rather use below approach. You will have 3x21=63 entries in the that list for _TABLE_SUFFIX - but you will be able to get around your issue with query length
FROM `nsimplbigquery.TaskManagement.*`
WHERE _TABLE_SUFFIX IN (
'C7s_2018_47_11',
'C7s_2018_45_11',
'C7s_2018_46_11',
'C7z_2018_47_11',
'C7z_2018_45_11',
'C7z_2018_46_11',
'C7u_2018_47_11',
'C7u_2018_45_11',
'C7u_2018_46_11',
...
...
...
'C7r_2018_47_11',
'C7r_2018_45_11',
'C7r_2018_46_11',
)

PL/SQL: Invalid Number error

I am creating a procedure for which I collect data by repeatedly running the following query.
SELECT ATTRIBUTE_VALUE,
COUNT(src1) CNT1,
COUNT(src2) CNT2
FROM (
SELECT a.ATTRIBUTE_VALUE,
1 src1,
TO_NUMBER(NULL) src2
FROM (
SELECT DECODE(
L,
1, IP_ADDRESS,
DECODE(
L,
2, IP_SUBNET_MASK,
DECODE(
L,
3, IP_DEFAULT_GATEWAY
)
)
) ATTRIBUTE_VALUE
FROM ( SELECT LEVEL L FROM DUAL X CONNECT BY LEVEL <= 3 ),
REUT_LOAD_IP_ADDRESSES
WHERE LIP_IPT_NAME = 'CE'
AND IP_LNT_ID IN (
SELECT LNT_ID
FROM REUT_LOAD_NTN
WHERE LNT_ID IN (
SELECT RLPN.LPN_LNT_ID
FROM REUT_LOAD_PI_NTN RLPN
WHERE LPN_LPI_ID IN (
SELECT RLPI.LPI_ID
FROM REUT_LOAD_PAC_INS RLPI
WHERE RLPI.LPI_DATE_ADDED IN (
SELECT MAX(RLPI2.LPI_DATE_ADDED)
FROM REUT_LOAD_PAC_INS RLPI2
WHERE RLPI2.PI_JOB_ID = P_ORDER_ID
)
)
)
AND IP_CEASE_DATE IS NULL
AND LNT_SERVICE_INSTANCE = 'PRIMARY'
)
It is running fine in SQL developer but when executing it as a procedure, I am getting INVALID NUMBER ERROR (ORA-01722: invalid number) at
AND IP_LNT_ID IN (
SELECT LNT_ID, in the code.
Can I get any help?
The error is pretty clear. You're comparing a number to another type of value.
Example:
SELECT 'x'
FROM DUAL
WHERE 1 IN (SELECT 'a'
FROM DUAL)
This means that IP_LNT_ID, LNT_ID, LPN_LNT_ID and LPI_ID have to be NUMBER. And LPI_DATE_ADDED and LPI_DATE_ADDED should both be date or timestamp.
If this is not possible you could compare everything as char:
SELECT ATTRIBUTE_VALUE, COUNT(src1) CNT1, COUNT(src2) CNT2
FROM (SELECT a.ATTRIBUTE_VALUE, 1 src1, TO_NUMBER(NULL) src2
FROM (SELECT
DECODE(L,1,IP_ADDRESS,DECODE(L,2,IP_SUBNET_MASK,DECODE(L,3,IP_DEFAULT_GATEWAY) ) ) ATTRIBUTE_VALUE
FROM
(
SELECT LEVEL L FROM DUAL X CONNECT BY LEVEL <= 3
),
REUT_LOAD_IP_ADDRESSES
WHERE LIP_IPT_NAME = 'CE'
AND to_char(IP_LNT_ID) IN (
SELECT LNT_ID
FROM REUT_LOAD_NTN
WHERE to_char(LNT_ID) IN (
SELECT RLPN.LPN_LNT_ID
FROM REUT_LOAD_PI_NTN RLPN
WHERE to_char(LPN_LPI_ID) IN (
SELECT RLPI.LPI_ID
FROM REUT_LOAD_PAC_INS RLPI
WHERE to_char(RLPI.LPI_DATE_ADDED) IN (
SELECT MAX(RLPI2.LPI_DATE_ADDED)
FROM REUT_LOAD_PAC_INS RLPI2
WHERE RLPI2.PI_JOB_ID = P_ORDER_ID
)
)
)
AND IP_CEASE_DATE IS NULL
AND LNT_SERVICE_INSTANCE = 'PRIMARY'
)
But this should be avoided on any cost. Unfortunately some times we have to cheat a little from time to time to work with our existing infrasructure ;-)
You need to make sure:
REUT_LOAD_IP_ADDRESSES.IP_LNT_ID
and
REUT_LOAD_NTN.LNT_ID
Have the same data type or cast/convert one or other so that they have the same data type.
There are multiple other issues:
You have aggregated and non-aggregated values:
SELECT ATTRIBUTE_VALUE,
COUNT(src1) CNT1,
COUNT(src2) CNT2
FROM ( ... )
Without a GROUP BY clause.
src2 is TO_NUMBER(NULL) which is just NULL and COUNT(NULL) will always be 0 so your query is:
SELECT ATTRIBUTE_VALUE,
COUNT(src1) CNT1,
0 CNT2
...
This code:
SELECT DECODE(
L,
1, IP_ADDRESS,
DECODE(
L,
2, IP_SUBNET_MASK,
DECODE(
L,
3, IP_DEFAULT_GATEWAY
)
)
) ATTRIBUTE_VALUE
FROM ( SELECT LEVEL L FROM DUAL X CONNECT BY LEVEL <= 3 ),
REUT_LOAD_IP_ADDRESSES
Can be rewritten as:
SELECT DECODE(
L,
1, IP_ADDRESS,
2, IP_SUBNET_MASK,
3, IP_DEFAULT_GATEWAY
) ATTRIBUTE_VALUE
FROM ( SELECT LEVEL L FROM DUAL X CONNECT BY LEVEL <= 3 ),
REUT_LOAD_IP_ADDRESSES
Or, without the join as:
SELECT attribute_value
FROM REUT_LOAD_IP_ADDRESSES
UNPIVOT ( attribute_value FOR L IN (
IP_ADDRESS AS 1,
IP_SUBNET_MASK AS 2,
IP_DEFAULT_GATEWAY AS 3
) )
The innermost query:
SELECT RLPI.LPI_ID
FROM REUT_LOAD_PAC_INS RLPI
WHERE RLPI.LPI_DATE_ADDED IN (
SELECT MAX(RLPI2.LPI_DATE_ADDED)
FROM REUT_LOAD_PAC_INS RLPI2
WHERE RLPI2.PI_JOB_ID = P_ORDER_ID
)
The inner query is restricted to have RLPI2.PI_JOB_ID = P_ORDER_ID but there is no correlation between the outer query so you can retrieve results that do not match P_ORDER_ID but just happen to have the same date as a matching row.

sql count new id that did not exists before for each month

I have the follow set of data
enter image description here
how can I write the sql to gives the result on right side?
that is the counting of unique id that did appeared previously for each month.
After long time of reading and reading his question, Ssiu wanted to ask the following:
So here is the test data in MS SQL: at that time he didn't clarify on postgresql
create table tmp1 (
ddate datetime
, iid int
)
insert into tmp1 values
('2017-11-01',1)
,('2017-11-02',2)
,('2017-11-03',3)
,('2017-11-04',4)
,('2017-11-05',5)
,('2017-11-06',5)
,('2017-11-07',5)
,('2017-12-01',1)
,('2017-12-02',2)
,('2017-12-03',3)
,('2017-12-04',6)
,('2017-12-05',7)
,('2018-01-01',1)
,('2018-01-02',2)
,('2018-01-03',3)
,('2018-01-04',4)
,('2018-01-05',8)
Disclaimer: The following is not the best approach for this problem. It is not applicable for more months, however it can give Ssiu a clue.
with cte(mmonth, iid) as (
select distinct convert(varchar(7), ddate, 120) mmonth
, iid
from tmp1
)
, cte_201711 as (
select * from cte where mmonth = '2017-11'
)
, cte_201712 as (
select * from cte where mmonth = '2017-12'
)
, cte_201801 as (
select * from cte where mmonth = '2018-01'
)
, cte_cnt201712 as(
select cte_201711.mmonth as mm201711
, cte_201711.iid as id201711
, cte_201712.mmonth as mm201712
, cte_201712.iid as id201712
from cte_201711
full outer join cte_201712
on cte_201712.iid = cte_201711.iid
)
, cte_cnt201801 as (
select cte_201711.mmonth as mm201711
, cte_201711.iid as id201711
, cte_201712.mmonth as mm201712
, cte_201712.iid as id201712
, cte_201801.mmonth as mm201801
, cte_201801.iid as id201801
from cte_201711
full outer join cte_201712
on cte_201712.iid = cte_201711.iid
full outer join cte_201801
on cte_201801.iid = cte_201712.iid
or cte_201801.iid = cte_201711.iid
)
--select * from cte_cnt201801 order by isnull(mm201711,'z'), isnull(mm201712,'z')
select '2017-12' mmonth, count(*) Ssiu
from cte_cnt201712
where mm201711 is null
union all
select '2018-01' mmonth, count(*) Ssiu
from cte_cnt201801
where mm201711 is null
and mm201712 is null
Note the data for the cte_cnt201801 CTE:
select * from cte_cnt201801 order by isnull(mm201711,'z'), isnull(mm201712,'z')
So the result for the above query is:

Trying to Get SELECT TOP to work with Parameter in ACCESS

This is building on some code I got the other day (thanks to peterm). I am now trying to select the TOP X number of results after calculations on the query. The X can range from 1 to 8 depending on the number of results per player.
This is the code I have but I get a syntax error when I try to run it.
SELECT
PlayerID
, RoundID
, PlayedTo
, (SELECT Count(PlayerID) FROM PlayedToCalcs) AS C
, iif(
C <= 6
, 1
, iif(
C <= 8
, 2
, (
iif(
C <= 10
, 3
, (
iif(
C <= 12
, 4
, (
iif(
C <= 14
, 5
, (
iif(
C <= 16
, 6
, (
iif(
C <= 18
, 7
, (iif(C <= 20, 8, 999))
)
)
)
)
)
)
)
)
)
)
)
) AS X
FROM PlayedToCalcs AS s
WHERE PlayedTo IN (
SELECT TOP (X) PlayedTo
FROM PlayedToCalcs
WHERE PlayerID = s.PlayerID
ORDER BY PlayedTo DESC, RoundID DESC
)
ORDER BY PlayerID, PlayedTo DESC, RoundID DESC;
Here is a link http://sqlfiddle.com/#!3/a726c/4 with a small sample of the data I'm trying to use it on.
The Access db engine does not allow you to use a parameter for SELECT TOP. You must include a literal value in the SQL statement.
For example this query works correctly.
SELECT TOP 2 *
FROM tblFoo
ORDER BY id DESC;
But attempting to substitute a parameter, how_many, triggers error 3141, "The SELECT statement includes a reserved word or an argument name that is misspelled or missing, or the punctuation is incorrect."
SELECT TOP how_many *
FROM tblFoo
ORDER BY id DESC;
The reason being in SQL Server (the simulator you used in SQL Fiddle), you cannot use IIF. Try using CASE.
And there is a limitation of using 7 nested IIF in Access.

Subquery within SubQuery in SQL - DB2

I am having issue when trying to make a the sub query shown in the first filter dynamically based on one of the results returned from the query. Can someone please tell me what I am doing wrong. In the first subquery it worked.
( SELECT
MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS
FROM
(
SELECT
MIN(TMP.D_DAT_INDEX_DATE) AS MIN_DATE,
MAX(TMP.D_DAT_INDEX_DATE) AS MAX_DATE,
SUM(INDEX_COUNT) AS SUM_INDEX
FROM
(
SELECT
D_DAT_INDEX_DATE,
INDEX_COUNT,
D_DAT_INDEX_DATE - (DENSE_RANK() OVER(ORDER BY D_DAT_INDEX_DATE)) DAYS AS G
FROM
DWH.MQT_SUMMARY_WATER_READINGS
WHERE
N_COD_METER_CNTX_KEY = 79094
) AS TMP
GROUP BY
TMP.G
ORDER BY
1
) ) AS MAX_NUM_CONS_DAYS
Above is the subquery I am trying to replace 123456 with CTXTKEY or CTXT.N_COD_METER_CNTX_KEY from query. Below is the full code. Please note than in the subquery before "MAX_NUM_CONS_DAYS" it worked. However, it was only one subquery down.
SELECT
N_COD_WM_DWH_KEY,
V_COD_WM_SN_2,
N_COD_SP_ID,
CTXKEY,
V_COD_MIU_SN,
N_COD_POD,
MIU_CAT,
V_COD_SITR_ASSOCIATED,
WO_INST_DATE,
WO_MIU_CAT,
DAYSRECEIVED3,
MAX_NUM_CONS_DAYS,
( CASE WHEN ( DAYSRECEIVED3 = 3 ) THEN 'Y' ELSE 'N' END ) AS GREEN,
( CASE WHEN ( DAYSRECEIVED3 < 3 AND DAYSRECEIVED3 > 0 ) THEN 'Y' ELSE 'N' END ) AS BLUE,
( CASE WHEN ( DAYSRECEIVED3 = 0 AND MAX_NUM_CONS_DAYS >= 5 ) THEN 'Y' ELSE 'N' END ) AS ORANGE,
( CASE WHEN ( DAYSRECEIVED3 = 0 AND MAX_NUM_CONS_DAYS BETWEEN 1 and 4 ) THEN 'Y' ELSE 'N' END ) AS RED
FROM
(
SELECT
WMETER.N_COD_WM_DWH_KEY,
WMETER.V_COD_WM_SN_2,
WMETER.N_COD_SP_ID,
CTXT.N_COD_METER_CNTX_KEY AS CTXKEY,
CTXT.V_COD_MIU_SN,
CTXT.N_COD_POD,
MIU.N_COD_MIU_CATEGORY AS MIU_CAT,
CTXT.V_COD_SITR_ASSOCIATED,
T1.D_DAT_PLAN_INST AS WO_INST_DATE,
T1.N_COD_MIU_CATEGORY AS WO_MIU_CAT,
( SELECT COUNT( DISTINCT D_DAT_INDEX_DATE ) FROM DWH.MQT_SUMMARY_WATER_READINGS WHERE ( N_COD_METER_CNTX_KEY = CTXT.N_COD_METER_CNTX_KEY ) AND D_DAT_INDEX_DATE BETWEEN ( '2013-07-10' ) AND ( '2013-07-12' ) ) AS DAYSRECEIVED3,
( SELECT
MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS
FROM
(
SELECT
MIN(TMP.D_DAT_INDEX_DATE) AS MIN_DATE,
MAX(TMP.D_DAT_INDEX_DATE) AS MAX_DATE,
SUM(INDEX_COUNT) AS SUM_INDEX
FROM
(
SELECT
D_DAT_INDEX_DATE,
INDEX_COUNT,
D_DAT_INDEX_DATE - (DENSE_RANK() OVER(ORDER BY D_DAT_INDEX_DATE)) DAYS AS G
FROM
DWH.MQT_SUMMARY_WATER_READINGS
WHERE
N_COD_METER_CNTX_KEY = 79094
) AS TMP
GROUP BY
TMP.G
ORDER BY
1
) ) AS MAX_NUM_CONS_DAYS
FROM DWH.DWH_WATER_METER AS WMETER
LEFT JOIN DWH.DWH_WMETER_CONTEXT AS CTXT
ON WMETER.N_COD_WM_DWH_KEY = CTXT.N_COD_WM_DWH_KEY
LEFT JOIN DWH.DWH_MIU AS MIU
ON CTXT.V_COD_MIU_SN = MIU.V_COD_MIU_SN
LEFT JOIN
( SELECT V_COD_CORR_WAT_METER_SN, D_DAT_PLAN_INST, N_COD_MIU_CATEGORY
FROM DWH.DWH_ORDER_MANAGEMENT_FACT
JOIN DWH.DWH_MIU
ON DWH.DWH_ORDER_MANAGEMENT_FACT.V_COD_MIU_SN = DWH.DWH_MIU.V_COD_MIU_SN
) AS T1
ON WMETER.V_COD_WM_SN_2 = T1.V_COD_CORR_WAT_METER_SN
WHERE
( V_COD_SITR_ASSOCIATED = 'X' )
AND ( ( MIU.N_COD_MIU_CATEGORY <> 4 ) OR ( ( MIU.N_COD_MIU_CATEGORY IS NULL ) AND ( ( T1.N_COD_MIU_CATEGORY <> 4 ) OR ( T1.N_COD_MIU_CATEGORY IS NULL ) ) ) )
)
Error I am getting is:
Error Code: -204, SQL State: 42704
I would say that a good option here would be to use a CTE, or Common Table Expression. You can do something similar to the following:
WITH CTE_X AS(
SELECT VAL_A
,VAL_B
FROM TABLE_A)
,CTE_Y AS(
SELECT VAL_C
,VAL_B
FROM TABLE_B)
SELECT VAL_A
,VAL_B
FROM CTE_X X
JOIN CTE_Y Y
ON X.VAL_A = Y.VAL_C;
While this isn't specific to your example, it does show that CTE's create a sort of temporary "in memory" table that you can access in a subsequent query. This should allow you to issue your inner two subselects as a CTE, and then use the CTE in the "SELECT MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS" query.
You cannot reference columns from the outer select in the subselect, no more than 1 level deep anyway. If I correctly understand what you're doing, you'll probably need to join DWH.MQT_SUMMARY_WATER_READINGS and DWH.DWH_WMETER_CONTEXT in the outer select.