Unknown column 'readingid' in 'where clause' - java

SELECT
a.objid AS acctid,
a.acctno,
a.name,
a.meterid,
m.serialno,
(
SELECT
objid
FROM
waterworks_meter_reading r
WHERE r.meterid = a.meterid
AND r.month = 6
AND r.year = 2015
LIMIT 1
) AS readingid
FROM waterworks_account a
INNER JOIN waterworks_meter m ON a.meterid = m.objid
INNER JOIN waterworks_account_address ad ON a.objid = ad.parentid
WHERE ad.barangayid LIKE '%'
AND readingid IS NULL
When I tried to execute the query above it throws an error: Unknown column 'readingid' in 'where clause'. Can someone explain to me why?

In SQL, you cannot reference a column alias defined in a select in the where clause at the same level (or elsewhere in the select).
MySQL has a convenient work-around, in some cases. You can reference it in a having clause. So this should do what you want:
WHERE ad.barangayid LIKE '%'
HAVING readingid IS NULL

I think the problem is that the "readingid" isn't really a column name. It exists in the select but that happens after the where clause. I would use a nested query to get the "readingid" so it is available for the where clause.
For example:
SELECT
a.objid AS acctid,
a.acctno,
a.name,
a.meterid,
m.serialno FROM waterworks_account a
INNER JOIN waterworks_meter m ON a.meterid = m.objid
INNER JOIN waterworks_account_address ad ON a.objid = ad.parentid
WHERE ad.barangayid LIKE '%'
AND NOT EXISTS (SELECT
objid
FROM
waterworks_meter_reading r
WHERE r.meterid = a.meterid
AND r.month = 6
AND r.year = 2015)

Related

coalesce mybatis switch case

Iam using coalesce mybatis switch case in my query, where iam getting error like
Error querying database. Cause: java.sql.SQLException: ORA-01427:
single-row subquery returns more than one row
this is my query
(select
(case when (coalesce(t1.col1,t2.col1, t1.col2, t1.col3) is null)
then (select sysdate from dual)
else (coalesce(t1.col1,t2.col1, t1.col2, t1.col3))
end )
from table1 t1
join table2 t2
on t1.id IN (t2.id))
Thanks in advance
Seems you have a lot of () but overall you should use = operator and not IN (t2.id) for join t2.id
select
case when coalesce(t1.col1,t2.col1, t1.col2, t1.col3) is null
then sysdate
else coalesce(t1.col1,t2.col1, t1.col2, t1.col3)
end
from table1 t1
join table2 t2 on t1.id = t2.id
And looking at the code you posted in sample you have a select as a column result and this select return several rows, ( this raise the error). You also have a mixin of join syntax some based on explicit join syntax some based on old implicit join syntax based on comma separated table name and where condition. You should try using this
<select id="Trigger" parameterType="hashmap" resultType="java.util.HashMap" flushCache="true">
SELECT
select case when coalesce(table1.col1, table2.col2,table1.col3, table1.col4) is null
then sysdate
else coalesce(table1.col1, table2.col2,table1.col3, table1.col4) end as "ProgressDate"
, table3.id as "ID"
from table1
INNER join table2 on table1.id = table2.id
INNER JOIN table3 ON table1.id = table3.id
INNER JOIN table4 table2.action = table4.action
WHERE table3.transaction = #{inputvaluepassed}
</select>
The query you mention in the question takes the place of a scalar subquery included in another... main query. I formatted the whole query (for readability) and it looks like this:
SELECT
(
select case when coalesce(table1.col1, table2.col2,table1.col3,
table1.col4) is null
then (select sysdate from dual)
else coalesce(table1.col1, table2.col2,table1.col3, table1.col4)
end
from table1
join table2 on table1.id = table2.id
) as "ProgressDate",
table3.id as "ID"
FROM table3, table1, table2, table4
WHERE table3.transaction = #{inputvaluepassed}
AND table1.id = table3.id
AND table2.id=table1.id and table2.action = table4.action
Now, by definition, scalar subqueries can only return zero or one row. In your case it seems that at runtime this subquery is returning multiple rows, and the main query crashes.
You'll need to somehow produce a single row at most: maybe by aggregating the rows (using GROUP BY), maybe by picking one row only from the result set (using LIMIT); there are other options. If we choose the to limit the rows to 1 at most your query could look like:
SELECT
(
select case when coalesce(table1.col1, table2.col2,table1.col3,
table1.col4) is null
then (select sysdate from dual)
else coalesce(table1.col1, table2.col2,table1.col3, table1.col4)
end
from table1
join table2 on table1.id = table2.id
limit 1 -- added this line
) as "ProgressDate",
table3.id as "ID"
FROM table3, table1, table2, table4
WHERE table3.transaction = #{inputvaluepassed}
AND table1.id = table3.id
AND table2.id=table1.id and table2.action = table4.action
This is just one possible cheap solution to the issue. A better understanding on how to pick the right row over multiples ones can produce a better solution.

JOOQ: Type class org.jooq.impl.SelectImpl is not supported in dialect DEFAULT

My question about writing query in jooq dsl.
I have some list of client attributes stored in an Oracle database.
Table structure is following:
CLIENT_ATTRIBUTE_DICT (ID, CODE, DEFAULT_VALUE) - list of all possible attributes
CLIENT_ATTRIBUTE (ATTRIBUTE_ID, CLIENT_ID, VALUE) - attributes values for different clients
I'm trying to select values of all existing attributes (in dict) for given client:
If exist row in CLIENT_ATTRIBUTE with given clientId than attribute value = CLIENT_ATTRIBUTE.VALUE else CLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE
My query in SQL (works fine):
SELECT d.code,
NVL
(
(
SELECT value
FROM CLIENT_ATTRIBUTE a
WHERE a.ATTRIBUTE_ID = d.id
AND a.CLIENT_ID = 1
),
(
SELECT DEFAULT_VALUE
FROM CLIENT_ATTRIBUTE_DICT dd
WHERE dd.id=d.id
)
) value
FROM CLIENT_ATTRIBUTE_DICT d;
My query in Jooq dsl:
ClientAttributeDictTable dict = CLIENT_ATTRIBUTE_DICT.as("d");
Map<String, String> attributes =
dsl.select(
dict.CODE,
DSL.nvl(
dsl.select(CLIENT_ATTRIBUTE.VALUE)
.from(CLIENT_ATTRIBUTE)
.where(
CLIENT_ATTRIBUTE.ATTRIBUTE_ID.eq(dict.ID),
CLIENT_ATTRIBUTE.CLIENT_ID.eq(clientId)
),
dsl.select(CLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE)
.from(CLIENT_ATTRIBUTE_DICT)
.where(CLIENT_ATTRIBUTE_DICT.ID.eq(dict.ID))
).as("value")
).from(dict)
.fetchMap(String.class, String.class);
When jooq query runs it fails with error message:
Caused by: Type class org.jooq.impl.SelectImpl is not supported in dialect DEFAULT
at org.jooq.impl.DefaultDataType.getDataType(DefaultDataType.java:757) ~[na:na]
at org.jooq.impl.DefaultDataType.getDataType(DefaultDataType.java:704) ~[na:na]
at org.jooq.impl.DSL.getDataType(DSL.java:14378) ~[na:na]
at org.jooq.impl.DSL.val(DSL.java:12766) ~[na:na]
at org.jooq.impl.Utils.field(Utils.java:802) ~[na:na]
at org.jooq.impl.DSL.nvl(DSL.java:8403) ~[na:na]
What am I doing wrong?
UPD
JOOQ version 3.7.2
The error is two-fold.
Your API usage is currently not supported (jOOQ currently doesn't accept Select types in the nvl() function). Write this instead:
DSL.nvl(
DSL.field(dsl.select(CLIENT_ATTRIBUTE.VALUE)
// ^^^^^^^^^ explicitly wrap the Select in a Field
.from(CLIENT_ATTRIBUTE)
.where(
CLIENT_ATTRIBUTE.ATTRIBUTE_ID.eq(dict.ID),
CLIENT_ATTRIBUTE.CLIENT_ID.eq(clientId))),
DSL.field(dsl.select(CLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE)
// ^^^^^^^^^ explicitly wrap the Select in a Field
.from(CLIENT_ATTRIBUTE_DICT)
.where(CLIENT_ATTRIBUTE_DICT.ID.eq(dict.ID)))
).as("value")
jOOQ (or rather, the Java compiler) cannot detect this API misusage, because the nvl() API is overloaded in a way that always compiles. This is issue https://github.com/jOOQ/jOOQ/issues/5340 and will be fixed in a future version (probably jOOQ 3.9)
I found workaround.
First I rewrited SQL query:
SELECT D.CODE, NVL(S.VALUE, D.DEFAULT_VALUE) ATTRIBUTE_VALUE
FROM CLIENT_ATTRIBUTE_DICT D
LEFT JOIN
(SELECT DD.ID,
A.VALUE
FROM CLIENT_ATTRIBUTE_DICT DD
JOIN CLIENT_ATTRIBUTE A
ON A.ATTRIBUTE_ID = DD.ID
WHERE A.CLIENT_ID = 1
) S ON S.ID = D.ID;
Than I express my query in JOOQ dsl:
String ID_FIELD_NAME = "ID";
String VALUE_FIELD_NAME = "VALUE"
ClientAttributeDictTable DICT_ATTRIBUTES = CLIENT_ATTRIBUTE_DICT.as("D");
Table<Record2<Long, String>> EXISTING_ATTRIBUTES =
dsl.select(CLIENT_ATTRIBUTE_DICT.ID, CLIENT_ATTRIBUTE.VALUE)
.from(CLIENT_ATTRIBUTE_DICT)
.join(CLIENT_ATTRIBUTE)
.on(CLIENT_ATTRIBUTE.ATTRIBUTE_ID.eq(CLIENT_ATTRIBUTE_DICT.ID))
.where(CLIENT_ATTRIBUTE.CLIENT_ID.eq(clientId))
.asTable("S", ID_FIELD_NAME, VALUE_FIELD_NAME);
Field<String> ATTRIBUTE_VALUE_FIELD =
nvl(
EXISTING_ATTRIBUTES.field(VALUE_FIELD_NAME, String.class),
DICT_ATTRIBUTES.DEFAULT_VALUE
).as("ATTRIBUTE_VALUE");
Map<String,String> attributes =
dsl.select(DICT_ATTRIBUTES.CODE, ATTRIBUTE_VALUE_FIELD)
.from(DICT_ATTRIBUTES)
.leftJoin(EXISTING_ATTRIBUTES)
.on(DICT_ATTRIBUTES.ID
.eq(EXISTING_ATTRIBUTES.field(ID_FIELD_NAME, Long.class))
)
.fetchMap(DICT_ATTRIBUTES.CODE, ATTRIBUTE_VALUE_FIELD);
In logs I found a little bit changed SQL query generated by JOOK:
SELECT D.CODE,
NVL(S.VALUE, D.DEFAULT_VALUE) ATTRIBUTE_VALUE
FROM CLIENT_ATTRIBUTE_DICT D
LEFT OUTER JOIN (
(SELECT NULL ID, NULL VALUE FROM dual WHERE 1 = 0
)
UNION ALL
(SELECT CLIENT_ATTRIBUTE_DICT.ID,
CLIENT_ATTRIBUTE.VALUE
FROM CLIENT_ATTRIBUTE_DICT
JOIN CLIENT_ATTRIBUTE
ON CLIENT_ATTRIBUTE.ATTRIBUTE_ID = CLIENT_ATTRIBUTE_DICT.ID
WHERE CLIENT_ATTRIBUTE.CLIENT_ID = 141
)
) S ON D.ID = S.ID;
Any ideas how to improve my workaround are appreciated.

db2 sqlstate 42972 error

I am getting this error when I am trying to execute this sql query
INSERT INTO
AGG_QUALITY
SELECT
QIF.DATEDM_ID,
'Status' AS BREAKDOWN_TYPE,
HCR.VALUE,
QIF.SCANDEFINITION_ID,
QIF.QUALITYISSUE_VALUE,
COUNT(QIF.QUALITYISSUEFACT_ID),
COUNT(QRF.QUALITYRESOLUTIONFACT_ID)
FROM
QUALITYISSUEFACT QIF,
HUBCODERECORD HCR,
ITEMSTATUS ITS
LEFT JOIN
QUALITYRESOLUTIONFACT QRF
ON
QIF.QUALITYISSUEFACT_ID = QRF.QUALITYISSUEFACT_ID
WHERE
QIF.DATEDM_ID > startDateDMId
AND QIF.DATEDM_ID <= endDateDMId
AND HCR.CODE = ITS.H_STATUS_TYPE
AND QIF.DIMENSION_ROM_PK = ITS.ITEMMASTER_ID
GROUP BY
QIF.DATEDM_ID, HCR.VALUE, QIF.SCANDEFINITION_ID, QIF.QUALITYISSUE_VALUE
;
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0338N An ON clause associated with a JOIN operator or in a MERGE statement
is not valid. LINE NUMBER=31. SQLSTATE=42972
Try like below with inner joins:
INSERT INTO
AGG_QUALITY
SELECT
QIF.DATEDM_ID,
'Status' AS BREAKDOWN_TYPE,
HCR.VALUE,
QIF.SCANDEFINITION_ID,
QIF.QUALITYISSUE_VALUE,
COUNT(QIF.QUALITYISSUEFACT_ID),
COUNT(QRF.QUALITYRESOLUTIONFACT_ID)
FROM
QUALITYISSUEFACT QIF
INNER JOIN
HUBCODERECORD HCR
ON QIF.DIMENSION_ROM_PK = ITS.ITEMMASTER_ID
INNER JOIN
ITEMSTATUS ITS
ON QIF.DIMENSION_ROM_PK = ITS.ITEMMASTER_ID
LEFT JOIN
QUALITYRESOLUTIONFACT QRF
ON
QIF.QUALITYISSUEFACT_ID = QRF.QUALITYISSUEFACT_ID
WHERE
QIF.DATEDM_ID > startDateDMId
AND QIF.DATEDM_ID <= endDateDMId
GROUP BY
QIF.DATEDM_ID, HCR.VALUE, QIF.SCANDEFINITION_ID, QIF.QUALITYISSUE_VALUE
;
see if it helps
Had the same error here. (note, my Table1 has NO rows)
On my side I could solve it by changing the additional (comma separated) table2 to a REAL inner join.
Example from
select xxx from Table1 t1, Table2 t2
where (t2.col1 = t1.col1) and (t1.col2 = "whatever")
to
select xxx from Table1 t1
INNER JOIN Table2 t2 ON (t2.col1 = t1.col1)
where (t1.col2 = "whatever")
Hope this helps someone else.
(problem occured on DB2 9.7)

Cryptic MSSQL error message

Previous related thread: Join in Query WHERE clause
I'm getting this error:
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '.'.
My SQL Statement:
SELECT products.id, products.name products.extended_description, products.catalogid, products.image1, products.image2, products.stock, products.price, manufacturer.manufacturer, products.weight
FROM products
JOIN manufacturer ON (products.manufacturer = manufacturer.id)
JOIN product_category ON (product_category.catalogid = products.catalogid)
JOIN category ON (category.id = product_category.id)
WHERE category.category_name = ?;
What do I have wrong here? My statement looks correct to me...
You are missing a comma between products.name and products.extended_description. It thinks that products.extended_description is the alias. If it is then put []s around it. [products.extended_description]. Otherwise put in the missing comma.
SELECT products.id, products.name, products.extended_description, products.catalogid,
products.image1, products.image2, products.stock, products.price,
manufacturer.manufacturer, products.weight
FROM products
JOIN manufacturer ON (products.manufacturer = manufacturer.id)
JOIN product_category ON (product_category.catalogid = product.catalogid)
JOIN category ON (category.id = product_category.id)
WHERE category.category_name = ?;
You forgot a comma after products.name
Should be:
SELECT products.id, products.name, products.extended_description, ...

Jave SQL executeQuery throws up error for valid sql statement

I am using java java.sql.* for querying from SQLite DB. I found a starnge issue where I write a sqlString as:
SELECT n.Name as Name,
c.Value as Value0,
d.Value as Value1
FROM (Table1 c inner join Table2 n on c.NameID = n.ID),
Table3 d
WHERE c.RunID = 1
and d.RunID = 2
and c.NameID = d.NameID
The statement stmt.executeQuery(sqlQuery) throws the following exception:
java.sql.SQLException: no such column: n.Name
at org.sqlite.DB.throwex(DB.java:288)
at org.sqlite.NativeDB.prepare(Native Method)
at org.sqlite.DB.prepare(DB.java:114)
at org.sqlite.Stmt.executeQuery(Stmt.java:89).............
Name is already part of the Table2 table. The same statement is working fine from SQLite command prompt. But when I remove the open brackets and try to execute from java, there is no problem. Any idea why this happens so?
Try something like this, use sub resultset
SELECT rs1.Name AS NAME,
rs1.Value0 AS Value0,
d.Value AS Value1
FROM (SELECT n.Name AS NAME,
c.Value AS Value0,
d.Value AS Value1
FROM Table1 c INNER JOIN Table2 n ON c.NameID = n.ID) rs1,
Table3 d
WHERE c.RunID = 1
AND d.RunID = 2
AND c.NameID = d.NameID
The variables used in inner queries could not be referred outside. For example, you have used the variable n in inner sql. But you are referring it outside. The variable n is out of it's scope there.
Hi Friends Thanks for your fast responses. I am able to solve this problem. I am sharing this so if any1 else get this problem can do this:
SELECT ABC.Name as Name, ABC.Value as Value0, d.Value as Value1
FROM
(select n.Name as Name, c.Value as Value0 from Table1 c
inner join Table2 n on c.NameID = n.ID) AS ABC,
Table3 d ......;
Regards,Tor

Categories

Resources