SQL query multiple joins not working - oracle

I am using oracle database and trying to run the following query but it gives the error:
"ERROR at line 17: ORA-00904: "FRH"."NS": invalid identifier"
What is the problem with it?
Following is the query:
SELECT *
FROM
(SELECT *
FROM ROOMS R
WHERE R.Prix<'50') FRM
JOIN
(SELECT *
FROM
(SELECT *
FROM HOTELS H
WHERE H.CatH=2) FH
JOIN
(SELECT *
FROM RESORTS R
WHERE TypeS='montagne') FR
ON FH.NS=FR.NS) FRH
ON (FRH.NS=FRM.NS AND FRH.NH=FRM.NH);
Thanks in advance

You have way too many nested selects here. Your query can be simplified to:
SELECT *
FROM rooms rm
JOIN hotels ht ON ht.ns = rm.ns AND ht.nh = rm.nh
JOIN resorts rs ON rs.ns = ht.ns
WHERE rm.prix < 50
AND ht.cath = 2
AND ss.types = 'montagne';
I am not entirely sure which tables need to be joined using just the ns column and which need both the ns and nh column because you have obfuscated your query so much and did not show us the table definitions.
Alternatively you can move the restrictions on the joined tables into the join condition. This isn't necessary for the inner joins you are using, but could be needed if you ever want to change that to an outer join:
SELECT *
FROM rooms rm
JOIN hotels ht ON ht.ns = rm.ns AND ht.nh = rm.nh AND ht.cath = 2
JOIN resorts rs ON rs.ns = ht.ns AND rs.types = 'montagne'
WHERE rm.prix < 50;
You should also not compare numbers and strings. Assuming rooms.prix is a number column, the condition R.Prix<'50' is wrong. You need to compare the number to a number r.prix < 50

Related

MAX DATE with Multiple tables/Inner Joins in Toad/Oracle

I have only been using Toad/Oracle for a few weeks so am still learning coding etc I have knowledge of SQL Code in Access and trying to now learn Oracle.
I need to return the max date from UCMRBILDAT from tbl BIC/AZUCDMO0100 but only from contracts which are contained in linked tbl LH_DAT
I have also tried a having MAX UCMRBILDAT but this didnt work.
UCMRBILDAT (/BIC/AZUCDMO0100)
UC_MRESULT (/BIC/AZUCDMO0100)
UC_MRSTAT (/BIC/AZUCDMO0100
UC_MRCAT (/BIC/AZUCDMO0100)
CONTRACT_NUMBER (LH_DAT)
UC_MR_NUMB (/BIC/AZUCDMO0100) + (/BIC/AZUCDMO0200)
SELECT UCMRBILDAT,
UC_MRESULT,
UC_MRSTAT,
UC_MRCAT
FROM LH_DAT
( SELECT CONTRACT_NUMBER, MAX (UCMRBILDAT) MXBD
FROM SAPSR3."/BIC/AZUCDMO0100"
GROUP BY CONTRACT_NUMBER) GMR
LEFT OUTER JOIN SAPSR3."/BIC/AZUCDMO0200"
ON (CONTRACT_NUMBER = UCCONTRACT)
INNER JOIN SAPSR3."/BIC/AZUCDMO0100"
ON ("/BIC/AZUCDMO0200".UC_MR_NUMB = "/BIC/AZUCDMO0100".UC_MR_NUMB)
WHERE CONTRACT_NUMBER = '2000014420'
AND UCMRBILDAT = MXBD
AND MR.CONTRACT_NUMBER = GMR.CONTRACT_NUMBER
Max bill date from BIC/AZUCDMO0100 but only for contracts contained in table LH_DAT
EDIT NEED MAX DATE FOR UCMRBILDAT ON BELOW SCRIPT
SELECT CONTRACT_NUMBER,
UCMRBILDAT,
UC_MRESULT,
UC_MRCAT
FROM LH_DAT
LEFT OUTER JOIN SAPSR3."/BIC/AZUCDMO0200"
ON (CONTRACT_NUMBER = UCCONTRACT)
INNER JOIN SAPSR3."/BIC/AZUCDMO0100"
ON ("/BIC/AZUCDMO0200".UC_MR_NUMB = "/BIC/AZUCDMO0100".UC_MR_NUMB)
WHERE CONTRACT_NUMBER = '2000014420'
AND "/BIC/AZUCDMO0200".SOURSYSTEM = 'SP'
AND "/BIC/AZUCDMO0200".UCDELE_IND <> 'X'
To get the max value of "BIC/AZUCDMO0100".UCMRBILDAT where there's a linked value from LH_DAT you'd want to use:
SELECT MAX(ba.UCMRBILDAT)
FROM SAPSR3."BIC/AZUCDMO0100" ba
INNER JOIN LH_DAT ld
ON ld.some_field = ba.some_field
There must be fields which link "BIC/AZUCDMO0100" and LH_DAT together, but in your query they're not specified. Find those fields, plug them in to the query above, and you should get the result you're looking for.

sql select records that don't have relation in a third table

I have three tables
CLAIMS_TB
CLAIMS_RISK_TB
VEHICLE_TB
And then I need this result below:
Who can help me or share with me the query to be used?
N.B: If the code is 700 it means that it is a vehicle and it must fill the column called "ai_vehicle_use" otherwise it must leave it blank because "VEHICLE_TB" table contains only vehicles
This is what I tried:
select
klm.CM_PL_INDEX,
klm.cm_no,
klmrisk.cr_risk_code,
CASE WHEN klm.CM_PR_CODE = '0700' THEN klmrisk.cr_risk_code ELSE '' END,
veh.ai_vehicle_use
from CLAIMS_TB klm
JOIN CLAIMS_RISK_TB klmrisk
ON (klm.cm_index = klmrisk.cr_cm_index)
INNER JOIN VEHICLE_TB veh
on veh.ai_regn_no = klm.cm_no
where klm.cm_no='CL/01/044/00001/01/2018'
or klmrisk.cr_cm_index='86594'
order by klmrisk.cr_risk_code;
I believe this could fit your needs.
SELECT
*
FROM CLAIMS_TB AS c
LEFT JOIN CLAIMS_RISK_TB cl ON c.cm_index = cl.cr_cm_index
LEFT JOIN VEHICLE_TB v ON cl.cr_risk_code = v.ai_risk_index
Finaly I find the solution, query below works:
select * from CLAIMS_TB c
JOIN CLAIMS_RISK_TB cr ON( C.CM_INDEX = cr.cr_cm_index)
LEFT OUTER JOIN VEHICLE_TB v ON (cr.cr_risk_code = v.ai_regn_no);

Join 3 table to find total cost

We need to find out total cost for each project in XYZ company (from the project). Total cost is considered to be sum of (unit price * quantity) from invoice details table.
To find out total cost for each project you need join 3 tables in the query: XYZ_PROJECTS with XYZ_INVOICES (using PROJECT_NUMBER) and XYZ_INVOICES with XYZ_INVOICE_DETAILS (using INVOICE_NUMBER).
Go to SQL WorkshopSQL Commands. Write and execute a “select” query to select project number, project name from XYZ_PROJECTS, sum(c.qty * c.Unit_price) from XYZ_INVOICE_DETAILS. (You need to add “group by project_number, project_name” at the end of the query since SUM aggregate function is used). Run the query. Your screen should like as follows
I used this to join table but I do not know how to join 3 table at the same time.
select *
from XYZ_PROJECTS c
join XYZ_INVOICES do on c.PROJECT_NUMBER = do.PROJECT_NUMBER
select *
from XYZ_INVOICES i
join XYZ_INVOICE_DETAILS do on i.INVOICE_NUMBER = do.INVOICE_NUMBER
Maybe I do it wrong. Please kindly help me.
select c.project_number, c.project_name, sum(do.qty * do.Unit_price)
from XYZ_PROJECTS c
join XYZ_INVOICES i
on c.PROJECT_NUMBER = i.PROJECT_NUMBER
join XYZ_INVOICE_DETAILS do
on i.INVOICE_NUMBER = do.INVOICE_NUMBER
group by c.project_number, c.project_name
If you need to include zero cost projects who do not have any invoices yet, use left outer join to keep all rows from XYZ_PROJECTS:
select c.project_number, c.project_name, sum(do.qty * do.Unit_price)
from XYZ_PROJECTS c
left join XYZ_INVOICES i
on c.PROJECT_NUMBER = i.PROJECT_NUMBER
left join XYZ_INVOICE_DETAILS do
on i.INVOICE_NUMBER = do.INVOICE_NUMBER
group by c.project_number, c.project_name

Cognos 8 Query to find all Report and Column Names

I want to query the meta data in Cognos 8 to find all report and column names. If possible, I'd like to include the column definitions.
Can I do this using a Cognos report or do I need to query some repository?
Thanks.
You can select a list of reports from the content store with the following query:
SELECT CMOBJNAMES_BASE.NAME AS ObjName, CMOBJECTS.PCMID, CMCLASSES.NAME AS ClassName, CMOBJPROPS7.spec
FROM CMOBJECTS
JOIN CMOBJNAMES_BASE ON CMOBJECTS.CMID = CMOBJNAMES_BASE.CMID
JOIN CMCLASSES ON CMOBJECTS.CLASSID = CMCLASSES.CLASSID
LEFT JOIN CMOBJPROPS7 ON CMOBJECTS.CMID = CMOBJPROPS7.CMID
WHERE CMOBJECTS.CLASSID IN (10, 37)
ORDER BY CMOBJECTS.PCMID;
I use that in Cognos 10. I believe in cognos 8 the CMOBJNAMES_BASE table is actually named 'CMOBJNAMES' without the _BASE.
UPDATE: Has been tested and works in Cognos 11r9.
The Report metadata is stored in the 'SPEC' column of CMOBJPROPS7 as XML. You can parse this XML in order to strip out the columns used in the report. It will not be a simple task.
If you have time but not money, you can write your own code to parse that XML. If you have more money than time, you can buy a 3rd party program to accomplish this, such as Motio or BSP Metamanager.
The query above is less useful for building a clean list of columns, but great for searching for specific data items. For example, you have column you are wanting to change in a data source, but you are not sure which report uses that column. Run the query above, and search for the data item. It will be embedded within the XML in the Cognos MDX format, ie. [Presentation View].[Sales Summary].[Sales]
EDIT: As requested below, here is a query that includes folder paths.
-- List of Reports, the folder they are in, and the package they are using
select distinct temp2.name as package,temp1.folder,temp1.name from
(SELECT temp.PARENTNAME AS FOLDER,CMOBJECTS.PCMID,CMOBJNAMES.CMID, CMOBJNAMES.LOCALEID, CMOBJNAMES.MAPDLOCALEID, CMOBJNAMES.ISDEFAULT, CMOBJNAMES.NAME,
CMOBJECTS.CLASSID
FROM CMOBJNAMES INNER JOIN
CMOBJECTS ON CMOBJNAMES.CMID = CMOBJECTS.CMID
INNER JOIN
(SELECT P.CMID AS PARENT,P.NAME AS PARENTNAME FROM CMOBJNAMES P where P.LOCALEID between 24 and 52) temp
ON CMOBJECTS.PCMID = TEMP.PARENT
WHERE (CMOBJECTS.CLASSID = 10)
AND SUBSTR(TEMP.PARENTNAME,1,1) NOT IN ('1','2','3','4','5','6','7','8','9') AND
TEMP.PARENTNAME NOT LIKE 'Backup%') temp1
inner join
(SELECT CMREFNOORD1.CMID AS PID, CMREFNOORD1.REFCMID, CMOBJNAMES.NAME
FROM CMREFNOORD1 INNER JOIN
CMOBJECTS ON CMREFNOORD1.REFCMID = CMOBJECTS.CMID INNER JOIN
CMOBJNAMES ON CMOBJECTS.CMID = CMOBJNAMES.CMID
WHERE (CMREFNOORD1.PROPID = 31 AND CMOBJNAMES.LOCALEID between 24 and 52)) temp2
on temp1.cmid = temp2.pid and LOCALEID between 24 and 52;
Not sure if this will help anybody, but our version doesn't have a table named CMOBJNAMES_BASE.
This is what works for me:
select ob2.cmid, c.name as classname, n.name as objectname, o.DELIVOPTIONS as deliveryoptions, z2.name as owner
from CMOBJPROPS2 p
inner join CMOBJPROPS26 o on p.cmid=o.cmid
inner join CMOBJECTS ob on ob.cmid=o.cmid
inner join CMOBJECTS ob2 on ob.pcmid=ob2.cmid
inner join CMOBJNAMES n on n.cmid=ob2.cmid
inner join CMCLASSES c on ob2.classid=c.classid
left join CMREFNOORD2 z1 on z1.cmid = p.cmid
left join CMOBJPROPS33 z2 on z2.CMID = z1.REFCMID
where ACTIVE = 1 order by z2.name, objectName

Best way to exclude records from multiple tables

I got the following tables (just an example): vehicles, vehicle_descriptions, vehicle_parts
vehicles have 1 to many with vehicle_descriptions and vehicle_parts. There may not be a corresponding vehicle_description/part for a given vehicle.
SELECT * FROM vehicles
LEFT OUTER JOIN vehicles d ON vehicles.vin = d.vin AND d.summary NOT LIKE 'honda'
LEFT OUTER JOIN
(SELECT SUM(desc_total) FROM vehicle_descriptions WHERE NOT LIKE desc 'honda' GROUP BY vin) b
ON vehicles.vin = vehicle_b.vin
LEFT OUTER JOIN
(SELECT SUM(part_count) FROM vehicle_parts WHERE part_for NOT LIKE 'honda' GROUP BY vin) c ON vehicles.vin = c.vin
If either vehicle_desc, vehicles, or part contains the exclusion term, the whole record should not show up in the result set. The query above will return a record even if one of the tables contain the exclusion term Honda. How would I fix the above query?
You're not using any of the information in either sum() as part of what you show, just to decide whether to include the vehicle. And you're doing an unnecessary self join in your first clause. Generally in situations like this, the "exists" and "not exists" clauses work well. So what about this? I'll use Oracle syntax, you can convert to ANSI of course.
SELECT * FROM vehicles v where summary <> 'honda'
and not exists (select 1 from vehicle_descriptions d where d.vin = v.vin and d.desc <> 'honda')
and not exists (select 1 from vehicle_parts p where p.vin = v.vin and p.part_for <> 'honda')

Resources