How to execute subquery in Oracle? My query gets parentheses erro - sql

I'm trying to execute a query inside LabVIEW so I can informations stored in a Oracle Database, but when a try to execute a query with parenthesis it doesn't works and gives me this erro:
ADO Error: 0x80004005 Exception occured in Microsoft OLE DB Provider for ODBC Drivers: [Oracle][ODBC][Ora]ORA-00907: parêntese direito não encontrado
Here is the SQL query I'm trying to execute:
SELECT
F.CODIGOFAIXAMODELO,
F.CODIGOMODELO,
F.INICIOESCALA,
F.FUNDOESCALA,
F.FAIXA,
F.DESCFAIXA,
F.ORDEM,
P.CODIGOPROCEDIMENTO
FROM FAIXAS F INNER JOIN PROCEDS P ON F.CODIGOFAIXAMODELO=(
SELECT
CODIGOFAIXAMODELO
FROM PROCEDS
WHERE
PROCEDS.CODIGOFAIXAMODELO=F.CODIGOFAIXAMODELO
LIMIT 1
)
WHERE
F.CODIGOMODELO='%CODIGOMODELO%'
ORDER BY F.ORDEM ASC;
The %CODIGOMODELO% is replaced with a value by LabVIEW.
When I try the following Query it works:
SELECT
F.CODIGOFAIXAMODELO,
F.CODIGOMODELO,
F.INICIOESCALA,
F.FUNDOESCALA,
F.FAIXA,
F.DESCFAIXA,
F.ORDEM,
P.CODIGOPROCEDIMENTO
FROM FAIXAS F INNER JOIN PROCEDS P ON F.CODIGOFAIXAMODELO=P.CODIGOFAIXAMODELO
WHERE
F.CODIGOMODELO='%CODIGOMODELO%'
ORDER BY F.ORDEM ASC;
The problem with the second solution is that it returns me many P.CODIGOPROCEDIMENTO, and what I want is to get only one even when there are many.

there is no LIMIT function in Oracle
you need to use ROWNUM = 1 or OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
Also as it is stated by #APC, you shouldn't be joining your table on a subquery.

I would write it this way. It may be more efficient and more readable to avoid trying to evaluate a subquery inside an expression:
SELECT
F.CODIGOFAIXAMODELO,
F.CODIGOMODELO,
F.INICIOESCALA,
F.FUNDOESCALA,
F.FAIXA,
F.DESCFAIXA,
F.ORDEM,
P.CODIGOPROCEDIMENTO
FROM FAIXAS F
INNER JOIN (
SELECT
P1.CODIGOFAIXAMODELO,
MAX(P1.CODIGOPROCEDIMENTO) AS CODIGOPROCEDIMENTO
FROM PROCEDS P1
GROUP BY P1.CODIGOFAIXAMODELO
) P ON P.CODIGOFAIXAMODELO = F.CODIGOFAIXAMODELO
WHERE F.CODIGOMODELO = '%CODIGOMODELO%'
ORDER BY F.ORDEM ASC;
MAX() is an Aggregate Function that will return only one value for each group - specified in the GROUP BY clause. Therefore, using a subquery and joining on CODIGOFAIXAMODELO ensures that only one row is filtered against the main query.
The results really depend on the key structures, datatypes and how many rows are available in PROCEDS. There are of course other, more complex methods to achieve the same result, such as using Analytic Functions.

I think you can write it this way:
SELECT
F.CODIGOFAIXAMODELO,
F.CODIGOMODELO,
F.INICIOESCALA,
F.FUNDOESCALA,
F.FAIXA,
F.DESCFAIXA,
F.ORDEM,
P.CODIGOPROCEDIMENTO
FROM FAIXAS F INNER JOIN PROCEDS P ON F.CODIGOFAIXAMODELO=P.CODIGOFAIXAMODELO and ROWNUM = 1
WHERE
F.CODIGOMODELO='%CODIGOMODELO%'
ORDER BY F.ORDEM ASC;

Related

SQL Math Operation In Correlated Subquery

I am working with three tables, basically, one is a bill of materials, one contains part inventory, and the last one contains work orders or jobs. I am trying to find out if it is possible to have a correlated subquery that can perform a math operation using a value from the outer query. Here's an example of what I'm trying to do:
SELECT A.work_order,A.assembly,A.job_quantity,
(SELECT COUNT(X.part_number)
FROM bom X
WHERE X.assembly = A.assembly
AND (X.quantity_required * A.job_quantity) >= (SELECT Y.quantity_available FROM inventory Y WHERE
Y.part_number = X.part_number)) AS negatives
FROM work_orders A
ORDER BY A.assembly ASC
I am attempting to find out, for a given work order, if there are parts that we do not have enough of to build the assembly. I'm currently getting an "Error correlating fields" error. Is it possible to do this kind of operation in a single query?
Try moving the subquery to a join, something like this:
SELECT a.work_order, a.assembly, a.job_quantity, n.negatives
FROM work_orders a JOIN (SELECT x.part_number, COUNT(x.part_number) as negatives
FROM bom x JOIN work_orders b
ON x.assembly = b.assembly
WHERE (x.quantity_required * b.job_quantity) >= (SELECT y.quantity_available
FROM inventory y WHERE
y.part_number = x.part_number)
GROUP BY x.part_number) n
ON a.part_number = n.part_number
ORDER BY a.assembly ASC
Or create a temporary cursor with the subquery and then use it to join the main table.
Hope this helps.
Luis

strange Hibernate-generated SQL with OVER() function and ORDER BY ORDER ON

I'm having a problem with a slight ordering anomaly in a legacy web application, and figured I'd start with the back-end SQL query generated by Hibernate with DB2Dialect:
FROM (SELECT inner2_.*,
ROWNUMBER()
OVER(
ORDER BY ORDER OF inner2_) AS rownumber_
FROM (SELECT this_.sohn AS SOHN1_15_11_,
this_.aslc AS ASLC2_15_11_,
this_.cc AS CC3_15_11_,
bb1_.sbn AS SBN1_2_0_,
bb1_.abc AS ABC3_4_5_,
mh2_.smhn AS SMHN1_9_1_,
mh2_.sabc AS SABC3_4_6_,
og8_.sogn AS SOGN1_11_2_,
og8_.sogo AS SOGO3_4_7_,
oc9_.socn AS SOCN_1_13_3_,
oc9_.soco AS SOCO_3_4_8_
FROM ott.oh this_
INNER JOIN ott.bb1_
ON this_.sbn = bb1_.sbn
INNER JOIN ott.mh2_
ON this_.smhn = mh2_.smhn
LEFT OUTER JOIN ott.og og8_
ON this_.sogn = og8_.sogn
LEFT OUTER JOIN ott.oc oc9_
ON this_.socn = oc9_.socn
WHERE ( 1 = 1 )
AND bb1_.sbn = ?
AND mh2_.smhn = ?
FETCH first 200 ROWS only) AS inner2_) AS inner1_
WHERE rownumber_ > 190
ORDER BY rownumber_
What does this query do? I am especially curious about OVER(), which isn't coming up when I google for such a SQL function (but it is an MDX function?).
This query functions in the application to grab the last page of a paginated list that is ordered by a field that doesn't even appear in the query. The query to populate the first page on initial load is different, and its generated SQL does ORDER BY the desired field.
So to get through this I need to understand how the query functions. Takers?
OVER() is part of so called OLAP functions - a good desrciption can be found in the DB2 SQL Cookbook - i.e. available here:
http://www.ids-system.de/images/Downloads/DB2V97CK.PDF
It is a group of really useful functions.
Also good additional stuff
http://www.ibm.com/developerworks/data/library/techarticle/dm-0401kuznetsov/

SQL COUNT FORM JOIN TABLES

I have the following sql command:
SELECT "USERNAME"."TOPICS".VALUE,
"USERNAME"."TOPICS".QID,
"USERNAME"."QUESTION".QRATING
FROM "USERNAME"."TOPICS" JOIN "USERNAME"."QUESTION"
ON "USERNAME"."TOPICS".QID = "USERNAME"."QUESTION".QID
AND "USERNAME"."TOPICS".VALUE = 'kia'
ORDER BY QRATING DESC
It works really well, but I want to count how many element returns. So I tried to use:
SELECT COUNT("USERNAME"."TOPICS".QID)
FROM "USERNAME"."TOPICS" JOIN "USERNAME"."QUESTION"
ON "USERNAME"."TOPICS".QID = "USERNAME"."QUESTION".QID
AND "USERNAME"."TOPICS".VALUE = 'kia'
ORDER BY QRATING DESC
But I get the error :
Column reference 'USERNAME.TOPICS.VALUE' is invalid. When the SELECT
list contains at least one aggregate then all entries must be valid
aggregate expressions.
What is the problem?
Hmmm. The ORDER BY should be getting the error, not the SELECT. However, your query would be much easier to understand using table aliases:
SELECT COUNT(t.QID)
FROM "USERNAME"."TOPICS" t JOIN
"USERNAME"."QUESTION" q
ON t.QID = q.QID AND t.VALUE = 'kia';
If the first query works, I see no reason why this would not (and your original without the ORDER BY should also work).

Multiple table query with count error

Whenever I add a count to the following select statement, it causes it to give me an error, and I'm not sure why:
select "WorkOrder"."WorkOrderID", "Vehicles"."Model", "Vehicles"."Color",
"Vehicles"."LicensePlate", COUNT("WorkOrderPart"."WorkPartID") AS "Parts"
FROM "WorkOrder", "Vehicles", "WorkOrderPart"
WHERE "WorkOrder"."VIN" = "Vehicles"."VIN" AND
"WorkOrder"."WorkOrderID" = "WorkOrderPart"."WorkOrderID";
Whenever I run this, I get the following error:
select "WorkOrder"."WorkOrderID", "Vehicles"."Model", "Vehicles"."Color",
*
ERROR at line 1:
ORA-00937: not a single-group group function
What can I do about this? I am running the SQL command line with an Oracle database.
When you have a count (or other aggregate function), you need to group by the non aggregated items
select
"WorkOrder"."WorkOrderID",
"Vehicles"."Model",
"Vehicles"."Color",
"Vehicles"."LicensePlate",
COUNT("WorkOrderPart"."WorkPartID") AS "Parts"
FROM "WorkOrder", "Vehicles", "WorkOrderPart"
WHERE "WorkOrder"."VIN" = "Vehicles"."VIN"
AND "WorkOrder"."WorkOrderID" = "WorkOrderPart"."WorkOrderID"
group by "WorkOrder"."WorkOrderID", "Vehicles"."Model", "Vehicles"."Color",
"Vehicles"."LicensePlate"
As an aside, it is considered good practice to use explicit joins (unless you're using a prehistoric version of oracle) instead of the where clause
FROM "WorkOrder"
inner join "Vehicles" on "WorkOrder"."VIN" = "Vehicles"."VIN"
left join "WorkOrderPart" on "WorkOrder"."WorkOrderID" = "WorkOrderPart"."WorkOrderID"

Whats wrong with this nested query?

I am trying to write a query to return the id of the latest version of a market index stored in a database.
SELECT miv.market_index_id market_index_id from ref_market_index_version miv
INNER JOIN ref_market_index mi ON miv.market_index_id = mi.id
WHERE mi.short_name='dow30'
AND miv.version_num = (SELECT MAX(m1.version_num) FROM ref_market_index_version m1 INNER JOIN ref_market_index m2 ON m1.market_index_id = m2.id )
The above SQL statement can be (roughly) translated into the form:
SELECT some columns FROM SOME CRITERIA MATCHED TABLES
WHERE mi.short_name='some name'
AND miv.version_num = SOME NUMBER
What I don't understand is that when I supply an actual number (instead of a sub query), the SQL statement works - also, when I test the SUB query used to determine the latest version number, that also works - however, when I attempt to use the result returned by sub query in the outer (parent?) query, it returns 0 rows - what am I doing wrong here?
Incidentally, I also tried an IN CLAUSE instead of the strict equality match i.e.
... AND miv.version_num IN (SUB QUERY)
That also resulted in 0 rows, although as before, when running the parent query with a hard coded version number, I get 1 row returned (as expected).
BTW I am using postgeresql, but I prefer the solution to be db agnostic.
The problem is probably that the max(version_num) doesn't exist for 'dow30'.
Try the following correlated subquery:
SELECT miv.market_index_id market_index_id
from ref_market_index_version miv INNER JOIN
ref_market_index mi
ON miv.market_index_id = mi.id
WHERE mi.short_name='dow30' AND
miv.version_num = (SELECT MAX(m1.version_num)
FROM ref_market_index_version m1 INNER JOIN
ref_market_index m2
ON m1.market_index_id = m2.id
where m1.short_name = 'dow30'
)
I added the where clause in the subquery.