When I run this SQL query:
SELECT
STUDENT.STUDENT_ID, FIRST_NAME, LAST_NAME, REGISTRATION_DATE
FROM
STUDENT
LEFT OUTER
JOIN ENROLLMENT ON STUDENT.STUDENT_ID = ENROLLMENT.STUDENT_ID
WHERE
NVL(ENROLLMENT.ENROLL_DATE, 0) = 0
AND STUDENT.REGISTRATION_DATE <= TO_DATE('02-15-2007', 'MM-DD-YYYY');
I get this error:
ORA00920 error: invalid relational operator
Can you replace this line in the query and try
Replace NVL(ENROLLMENT.ENROLL_DATE, 0) = 0
to
NVL(ENROLLMENT.ENROLL_DATE, SYSDATE) = SYSDATE
Now the new query will be
SELECT STUDENT.STUDENT_ID, FIRST_NAME, LAST_NAME, REGISTRATION_DATE
FROM
STUDENT
LEFT OUTER
JOIN ENROLLMENT ON STUDENT.STUDENT_ID = ENROLLMENT.STUDENT_ID
WHERE
NVL(ENROLLMENT.ENROLL_DATE, SYSDATE) = SYSDATE
AND STUDENT.REGISTRATION_DATE <= TO_DATE('02-15-2007', 'MM-DD-YYYY');
Related
I have 2 sub queries which are repeated and are very long so I want to give it a name and then refer that name in the query as mentioned in https://stackoverflow.com/a/3058938/6700081.
I have a Customers table with ID, Name, OrderID
I have the Orders table with ID (this is the order ID so it is also the Foreign key), Price, Order_Date
This is my original query which is working fine:
SELECT CUSTOMERS.name, ORDERS.price FROM
CUSTOMERS INNER JOIN ORDERS
ON (CUSTOMERS.ORDER_ID = ORDERS.ID)
WHERE ORDERS.PRICE = (SELECT MAX(ORDERS.PRICE) from ORDERS where ORDERS.ORDER_DATE <= (SELECT ADD_MONTHS((SELECT MIN(ORDER_DATE) FROM ORDERS), 12*10) from ORDERS WHERE ROWNUM = 1))
AND ORDERS.ORDER_DATE <= (SELECT ADD_MONTHS((SELECT MIN(ORDER_DATE) FROM ORDERS), 12*10) from ORDERS WHERE ROWNUM = 1);
I tried to change it to a named query as below:
WITH MAX_ORDER_DATE as (SELECT ADD_MONTHS((SELECT MIN(ORDER_DATE) FROM ORDERS), 12*10) from ORDERS WHERE ROWNUM = 1),
WITH MAX_ORDER_PRICE as (SELECT MAX(ORDERS.PRICE) from ORDERS where ORDERS.ORDER_DATE <= (MAX_ORDER_DATE))
SELECT CUSTOMERS.name, ORDERS.price FROM
CUSTOMERS INNER JOIN ORDERS
ON (CUSTOMERS.ORDER_ID = ORDERS.ID)
WHERE ORDERS.PRICE = (MAX_ORDER_PRICE)
AND ORDERS.ORDER_DATE <= (MAX_ORDER_DATE);
But I get an error related to invalid table name. What is wrong with this query?
Your corrected query:
WITH MAX_ORDER_DATE AS (
SELECT ADD_MONTHS((SELECT MIN(ORDER_DATE) FROM ORDERS), 12*10) AS max_date
FROM ORDERS
WHERE ROWNUM = 1
),
MAX_ORDER_PRICE AS (
SELECT MAX(ORDERS.PRICE) AS max_price
FROM ORDERS
WHERE ORDERS.ORDER_DATE <= (SELECT max_date FROM MAX_ORDER_DATE)
)
SELECT c.name, o.price
FROM CUSTOMERS c
INNER JOIN ORDERS o
ON c.ORDER_ID = o.ID
WHERE
o.PRICE = (SELECT max_price FROM MAX_ORDER_PRICE) AND
o.ORDER_DATE <= (SELECT max_date FROM MAX_ORDER_DATE);
The main issues I noticed with your syntax were that you repeated WITH for each common table expression, when you only need to state it once at the beginning of the definitions. Also, if you want to use the single values you define in the two CTEs, you should use a subquery against those CTEs. Finally, I added aliases to the columns you select in the CTEs.
How can I do this in Laravel ORM?
SELECT
s.id,
s.name AS NAME,
COALESCE(su.cnt, 0) AS SUBJECTs,
COALESCE(e.marks, 0) AS MARKS
FROM student s
LEFT JOIN
(
SELECT student_id, COUNT(*) AS cnt
FROM subject
GROUP BY student_id
) su
ON s.id = su.student_id
LEFT JOIN
(
SELECT student_id, SUM(mark) AS marks
FROM exam
GROUP BY student_id
) e
ON s.id = e.student_id;
I want to join between STUDENT and SUBJECT, STUDENT and EXAM. The problem is happening when I join the third table, it duplicates the results.
This is
DB::table('student as su')->selectRaw("
su.id,
su.name,
COALESCE(su.cnt, 0) as SUBJECTS,
COALESCE(e.marks, 0) as MARKS
")->leftJoin(DB::raw("(
SELECT student_id, COUNT(*) AS cnt
FROM subject
GROUP BY student_id
) su"), 's.id', '=', 'su.student_id')
->leftJoin(DB::raw("(
SELECT student_id, SUM(mark) AS marks
FROM exam
GROUP BY student_id
) e"), 's.id', '=', 'e.student_id')
The below query has some issues. The subquery that I use here runs without any errors when run separately. However if I run the whole query below it ends in error.
"Error while compiling statement: FAILED: ParseException line 13:30 cannot recognize input near 'select' 'max' '(' in expression specification"
select acct_num from table1
where ind = 'Y'
and b = (select max(yr_mth_num) from table2)
and st_dt = (select cast(max(st_dt) as date) from table2)
Try this:
SELECT T1.acct_num
FROM table1 T1
LEFT SEMI JOIN
(SELECT
max(yr_mth_num) as max_yr_mth_num,
cast(max(st_dt) as date) as max_st_dt
FROM table2) T2
ON T1.b = T2.max_yr_mth_num
AND T1.st_dt = T2.max_st_dt
AND T1.ind = 'Y'
I am building an Oracle query which has a case statement involved.
SELECT
CASE WHEN
((SELECT agent_or_group_id from trans_slot where slot_id =
(SELECT slot_id from trans_slot where slot_alias = 'PP' and measure_expiration > sysdate)) > 0)
/*The below subquery returns 1 row*/
THEN (SELECT agent_or_group_id from trans_slot where slot_id =
(SELECT slot_id from trans_slot where slot_alias = 'PP' and measure_expiration > sysdate))
ELSE
/* The below subquery returns 2 rows*/
(SELECT child_agent_id FROM agent_object_group_member WHERE parent_agent_id IN
(SELECT agent_or_group_id FROM trans_slot WHERE slot_id IN
(SELECT slot_id FROM trans_slot WHERE slot_alias = 'PP' AND measure_expiration > sysdate)
)
)
END
"Agent_ID" from DUAL;
When the run the subqueries independent they run fine. But running the whole query returns
ORA-01427: single-row subquery returns more than one row
01427. 00000 - "single-row subquery returns more than one row"
*Cause:
*Action:
If I understand what you're after, you can't do it like that. You'll need to use a left outer join and then chose the column value you want to display.
Here's a simplified example based on the SQL you provided:
WITH t1 AS (SELECT 1 ID FROM dual UNION ALL
SELECT 0 ID FROM dual UNION ALL
SELECT 2 ID FROM dual),
t2 AS (SELECT 10 child_id, 0 parent_id FROM dual UNION ALL
SELECT 20 child_id, 0 parent_id FROM dual UNION ALL
SELECT 30 child_id, 1 parent_id FROM dual UNION ALL
SELECT 40 child_id, 2 parent_id FROM dual)
---- end of mimicking two tables with the sample data in them. See the query below:
SELECT COALESCE(t2.child_id, t1.id) ID
FROM t1
LEFT OUTER JOIN t2 ON (t1.id = t2.parent_id AND t1.id = 0);
ID
----------
10
20
2
1
Here, I have used the t1 and t2 subqueries to mimic the output you'd get from your main subqueries in your original query.
Then we outer join t2 to t1 only where the t1.id = 0. By doing this, you can then simply choose the t2.child_id value if it exists, otherwise use the t1.id value.
(I realise that in your example, the t1 equivalent subquery would only generate 1 row, based on what you said, but I've included 3 rows so that you can see what the results would be based on the different ids.)
ETA:
In your case, the t1 subquery in my example above would be:
SELECT agent_or_group_id
from trans_slot
where slot_id = (SELECT slot_id
from trans_slot
where slot_alias = 'PP'
and measure_expiration > sysdate)
and the t2 subquery would be:
SELECT child_agent_id
FROM agent_object_group_member
WHERE parent_agent_id IN (SELECT agent_or_group_id
FROM trans_slot
WHERE slot_id IN (SELECT slot_id
FROM trans_slot
WHERE slot_alias = 'PP'
AND measure_expiration > sysdate))
I'm new to Oracle and having knowledge of MS SQL. I'm trying to get a phone number depending upon the user_id from Table2 and here is the business logic:
Case1: if a single match is found in Table1 then get it's respective toll free number from Table2
Case2: if no match is found in Table1 then get the default toll free number from Table2
Case3: if an multiple match is found in Table1 then for all those assigned_care_levels get the Care value from Table2 ordered by asc or desc and select the top row phone number.
I wrote the following query which works fine when I run it individually. However, when I cobine it using the if else statements I'm getting the following error ERROR: ORA-00907: missing right parenthesis. Here is my code:
if ((select count(distinct care_level) from Table1 where user_id = '100') > 0)
select phone from Table2 where care_level in (select distinct care_level from Table1 where user_id = '100')
and rownum = 1
order by care_level asc
else if((select count(distinct care_level) from Table1 where user_id = '100') = 0)
select phone from Table2 where care_level = 'default'
SET SERVEROUTPUT ON;
DECLARE
v_CARE_COUNT NUMBER := 0;
v_PHONE VARCHAr2(40) := NULL;
BEGIN
select count(distinct care_level)
into v_CARE_COUNT
from Table1
where user_id = '100';
IF(v_CARE_COUNT > 0) THEN
select phone into v_PHONE
from Table2
where care_level in
(select distinct care_level from Table1 where user_id = '100')
and rownum = 1;
ELSE
select phone into v_PHONE
from Table2
where care_level = 'default';
END IF;
DBMS_OUTPUT.PUT_LINE('PHONE is <'||v_PHONE||'>');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception : '||SQLERRM);
END;
/
EDIT: ( AS SIngle SQL)
SELECT PHONE
FROM TABLE2
WHERE CARE_LEVEL in
(
SELECT CARE_LEVEL FROM TABLE1 WHERE USER_ID='100'
UNION
SELECT CARE_LEVEL FROM TABLE1 WHERE CARE_LEVEL='default'
AND NOT EXISTS
(SELECT 'X' FROM TABLE1 WHERE USER_ID='100')
)
AND ROWNUM = 1;
The 'else if' syntax is wrong. In Oracle you need to use 'ELSIF' and complete the whole conditional statement with an 'END IF'. The SQL statements within should also be followed with a ;
Try:
IF ((select count(distinct care_level) from Table1 where user_id = '100') > 0) THEN
select phone from Table2 where care_level in (select distinct care_level from Table1 where user_id = '100')
and rownum = 1
order by care_level asc;
ELSIF ((select count(distinct care_level) from Table1 where user_id = '100') = 0) THEN
select phone from Table2 where care_level = 'default'; END IF