I want to update a table value using join in oracle(11g),
I have used rowid as join parameter for same table, Is it safe to use rowid as a join parameter.
Following is the query which i am using for updation, I have tested the same on local database it is working fine, but is there any scenario that there may be rowid mis-match?
MERGE
INTO GEOTAG g
USING (SELECT g2.rowid AS rid, um.RETAILER_CODE
FROM GEOTAG g2
JOIN RETAILER_AD_DSE b
ON b.CODE = g2.RETAILER_CODE
JOIN USER_HIERARCHY_MASTER um
ON um.RETAILER_PRIMARY_ETOPUP = b.RETAILER_PRIMARY_ETOPUP) src
ON (g.rowid = src.rid)
WHEN MATCHED THEN UPDATE
SET g.RETAILER_CODE = src.RETAILER_CODE;
A rowid will be unique in a table so if by "safe" you just mean that you'll be joining a row to itself then, yes, this is safe.
On the other hand, your code seems to be a rather overly complicated way to do a correlated update. I suspect you just want this (you can omit the WHERE EXISTS if the there will always be a matching row in retailer_ad_dse and user_hierarchy_master).
UPDATE geotag g
SET g.retailer_code = (SELECT code
FROM retailer_ad_dse rad
JOIN user_hierarchy_master uhm
ON uhm.retailer_primary_etopup = rad.retailer_primary_etopup
WHERE g.retailer_code = rad.code)
WHERE EXISTS (SELECT code
FROM retailer_ad_dse rad
JOIN user_hierarchy_master uhm
ON uhm.retailer_primary_etopup = rad.retailer_primary_etopup
WHERE g.retailer_code = rad.code)
Related
I have a JPQL subquery in which I want to return a list of customerIds that meet a specific condition based on a ManyToOne relationship as shown below:
SELECT c.customerId
FROM Customer c
INNER JOIN FETCH c.customersChild cc
LEFT JOIN FETCH c.childsPet cp on cp.name = 'Rover'
GROUP BY c.customerId
HAVING (COUNT(cp.name) / COUNT(*)) = 1
In this case, the customer should only be present in the list if all of their childrens' pet's names are Rover. The HAVING (COUNT(cp.name) / COUNT(*)) = 1 clause works as-is in Oracle (SQL), since COUNT(cp.name) counts the number of non-null rows for each customer, and COUNT(*) counts the total number of rows (including nulls present due to the left join) for each customer... I believe COUNT(cp.name) works in JPQL but it doesn't seem like there is equivalent for COUNT(*)... does anyone know if there is a way to count all the rows within a group including nulls?
I would suggest you rewrite your query to the more understandable anti-join variant:
SELECT c.customerId
FROM Customer c
WHERE NOT EXISTS (
SELECT 1
FROM c.customersChild cc
JOIN cc.childsPet cp
WHERE cp.name = 'Rover'
)
I've got table
CREATE TABLE stp2_vehicles.can_data (
id bigserial NOT NULL,
receive_time timestamp NOT NULL,
gps_frame_id int8 NULL
);
based on it I need to add criteria predicate required for bigger query.
What i need in where clausule is select returning ids of can_data - only one id for each gps frame the one with earliest timestamp.
So in sql it would look like this:
select cd.id
from stp2_vehicles.can_data cd
right join
(select gps_frame_id, min(receive_time) as min_time
from stp2_vehicles.can_data
group by gps_frame_id
) cd2 on cd.gps_frame_id = cd2.gps_frame_id and cd.receive_time = cd2.min_time
;
unfortunately criteria api doesn't support joining with result of subquery.
I've tried also approach with self join (should be supported by criteria api) but solution I came with seems too computationally complex or has errors I can't see:
select cd.id
from stp2_vehicles.can_data cd
inner join stp2_vehicles.can_data cd2 on cd.id=cd2.id
where cd.receive_time = (select min(receive_time) from stp2_vehicles.can_data cd3 where cd.gps_frame_id = cd3.gps_frame_id );
By the way:
I've managed to solve simpler case:
select min(cd.id) from can_data cd group by cd.gps_frame_id
CriteriaQuery<CANData> criteriaQueryCanData = cb.createQuery(CANData.class);
Subquery<Long> subquery = criteriaQueryCanData.subquery(Long.class);
Root<CANData> canDataSubRoot = subquery.from(CANData.class);
subquery
.select(cb.least(canDataSubRoot.<Long>get(CANData_.ID)))
.groupBy(canDataSubRoot.<Long>get(CANData_.GPS_FRAME));
Since the subquery seems to be "static", you can define an entity for the result of the subquery by using the #Subselect annotation.
I have two queries that I'm trying to join together.
In first_query TABLE2.PROCESS_ID, every PROCESS_ID is unique in that table. In second_query though there are several PROCESS_ID's with the same number in TABLE3, so I think I have to do a one-to-many join. The join_query I have is giving me an error ORA-00933: SQL command not properly ended which I'm assuming has something to do with the one-to-many relationship with the JOIN.
I'm not really sure how to resolve this. Any help would be much appreciated!
first_query = """
SELECT TABLE1.RULE_ID, TABLE2.STATUS, TABLE2.ERROR_MESSAGE, TABLE2.PROCESS_ID
FROM TABLE2 LEFT JOIN
TABLE1
ON TABLE1.RULE_ID = TABLE2.RULE_ID
WHERE TABLE1.RULE_NAME IN ('TEST1', 'TEST2')
"""
second_query = """
SELECT RECORDS_PROCESSED, PROCESS_ID, STATUS
FROM TABLE3
"""
join_query = """
SELECT RULE_ID, STATUS, ERROR_MESSAGE, PROCESS_ID
FROM (first_query) as query_1
INNER JOIN (second_query) as query_2
ON query_1.PROCESS_ID = query_2.PROCESS_ID
GROUP BY PROCESS_ID desc
"""
You can not select 4 columns and group by only one of them unles you include selected columns as part of aggregation fucntion(like max(), sum(),...). One of the options is this:
SELECT query_1.RULE_ID --1
, query_2.STATUS --2
, query_1.ERROR_MESSAGE --3
, query_1.PROCESS_ID --4
FROM (SELECT TABLE1.RULE_ID
, TABLE2.STATUS
, TABLE2.ERROR_MESSAGE
, TABLE2.PROCESS_ID
FROM TABLE2
LEFT JOIN TABLE1
ON TABLE1.RULE_ID = TABLE2.RULE_ID
WHERE TABLE1.RULE_NAME IN ('TEST1', 'TEST2')) query_1
INNER JOIN (SELECT RECORDS_PROCESSED
, PROCESS_ID
, STATUS
FROM TABLE3) query_2
ON query_1.PROCESS_ID = query_2.PROCESS_ID
GROUP BY query_1.RULE_ID
, query_2.STATUS
, query_1.ERROR_MESSAGE
, query_1.PROCESS_ID
Also please do consider using aliases like this(in your first query):
SELECT T1.RULE_ID
, T2.STATUS
, T2.ERROR_MESSAGE
, T2.PROCESS_ID
FROM TABLE2 T2
LEFT JOIN TABLE1 T1 ON T1.RULE_ID = T2.RULE_ID
WHERE T1.RULE_NAME IN ('TEST1', 'TEST2')
Also, apply the same logic with aliases on your final query or else you will have a different kind of error : "ORA-00918: column ambiguously defined"
Here is a small demo
CTE (i.e. the WITH factoring clause) might help.
WITH first_query
AS (SELECT table1.rule_id,
table2.status,
table2.error_message,
table2.process_id
FROM table2 LEFT JOIN table1 ON table1.rule_id = table2.rule_id
WHERE table1.rule_name IN ('TEST1', 'TEST2')),
second_query
AS (SELECT records_processed, process_id, status FROM table3)
SELECT a.rule_id,
a.status,
a.error_message,
a.process_id
FROM first_query a INNER JOIN second_query b ON a.process_id = b.process_id
GROUP BY you used is invalid; you can't group results by only one column. If results have to be unique, use select distinct. If you have to use group by, specify all columns returned by select (which leads you back to what distinct does), or see whether some column(s) have to be aggregates - in that case, group by makes sense.
Also, you should always use table aliases. Without them, query is invalid as database engine doesn't know which table those columns (if they share the same name) belong to.
I'm attempting to convert an Oracle MERGE statement to a MySQL Update statement. This particular MERGE statement only does an update (no inserts), so am unclear why the previous engineer used a MERGE statement.
Regardless, I know need to convert this to MySQL and am not clear as to how this is done. (side note, I'm doing this within a JAVA App)
Here is the MERGE statement :
MERGE INTO table1 a
USING
(SELECT DISTINCT(ROWID) AS ROWID FROM table2
WHERE DATETIMEUTC >= TO_TIMESTAMP('
formatter.format(dWV.getTime())
','YYYY-MM-DD HH24:MI:SS')) b
ON(a.ROWID = b.ROWID and
a.STATE = 'WV' and a.LAST_DTE = trunc(SYSDATE))
WHEN MATCHED THEN UPDATE SET a.THISIND = 'S';
My attempts goes something like this :
UPDATE table1 a
INNER JOIN table2 b ON (a.ROWID = b.ROWID
and a.STATE = 'WV'
and a.LAST_DTE = date(sysdate()))
SET a.THISIND = 'S'
WHERE DATETIMEUTC >= TO_TIMESTAMP('formatter.form(dWV.getTime())', 'YYYY-MM-DD HH24:MI:SS')
However, I'm unclear if this is actually doing the same thing or not?
As noted by you, the original Oracle MERGE statement only performs updates, no inserts.
The general syntax of your MySQL query looks ok compared to the Oracle version. Here is an updated version :
UPDATE table1 a
INNER JOIN table2 b
ON a.ROWID = b.ROWID
AND b.DATETIMEUTC >= 'formatter.form(dWV.getTime())'
SET a.THISIND = 'S'
WHERE
a.STATE = 'WV'
AND a.LAST_DTE = CURDATE()
Changes :
current date can be obtained with function CURDATE()
'YYYY-MM-DD HH24:MI:SS' is the default format for MySQL dates, hence you do not need to convert it, you may just pass it as is (NB1 : it is unclear what 'formatter.form(dWV.getTime())' actually means - NB2 : if you ever need to translate a string to date, STR_TO_DATE is your friend)
the filter conditions on table a are better placed in the WHERE clause, while those on table b would better belong in the INNER JOIN
I have a Set of columns and Tables, in respective drop downs, I am working on a Code to generate a dynamic SQL based on the Table-Column selection
It's working in case of simple Select statements but in the case of Multiple Joins, I am trying to figure out a Syntax for handlin Right and Left Joins.
Please help..this is the Error for SQL Syntax
1)
(Select dbo.Employee.Dept_ID,dbo.Employee.Emp_ID,dbo.Employee.Emp_Name,dbo.Employee_DataVal.DeptNo,
dbo.Employee_DataVal.EmpName,dbo.Employee_DataVal.EmpNo,dbo.Employee_DataVal.Salary,dbo.Emp_Sal.Emp_ID,dbo.Emp_Sal.Salary
FROM Employee
INNER JOIN Employee_DataVal
ON Employee.Dept_ID = Employee_DataVal.DeptNo
OR Employee_DataVal.EmpName = Employee.Emp_Name)
LEFT JOIN Emp_Sal
ON Employee.Emp_ID = Emp_Sal.Emp_ID
Incorrect syntax near the keyword 'LEFT'.
2)Select dbo.Employee.Dept_ID,dbo.Employee.Emp_ID,
dbo.Employee.Emp_Name,dbo.Employee_DataVal.DeptNo,
dbo.Employee_DataVal.EmpName,dbo.Employee_DataVal.EmpNo
,dbo.Emp_Sal.Emp_ID,dbo.Emp_Sal.Salary
FROM Employee INNER JOIN Employee_DataVal
ON Employee.Emp_ID = Employee_DataVal.EmpNo
AND Employee.Dept_ID = Employee_DataVal.DeptNo
LEFT JOIN Employee
ON Employee_DataVal.EmpName = Employee.Emp_Name
The objects "Employee" and "Employee" in the FROM clause have the same exposed names. Use correlation names to distinguish them.
PS: Running this sql on SQL server
This is a common problem when working with complex dynamic SQL strings on a string basis - the correct handling of the SQL syntax in its string form is difficult, and it is easy to create SQL injection vulnerabilities as well.
SQL builder APIs like jOOQ and others are very well suited for this task. I'm not sure what exactly the problem was in your case, but let's just assume that the last LEFT JOIN is optional in your query. You could write a query like this:
List<Field<?>> c = new ArrayList<>(Arrays.asList(
EMPLOYEE.DEPT_ID,
EMPLOYEE.EMP_ID,
EMPLOYEE.EMP_NAME,
EMPLOYEE_DATAVAL.DEPTNO,
EMPLOYEE_DATAVAL.EMPNAME,
EMPLOYEE_DATAVAL.EMPNO,
EMPLOYEE_DATAVAL.SALARY
));
Table<?> t = EMPLOYEE
.join(EMPLOYEE_DATAVAL)
.on(EMPLOYEE.DEPT_ID.eq(EMPLOYEE_DATAVAL.DEPTNO)
.or(EMPLOYEE_DATAVAL.EMPNAME.eq(EMPLOYEE.EMP_NAME));
if (someCondition) {
t = t.leftJoin(EMP_SAL).on(EMPLOYEE.EMP_ID.eq(EMP_SAL.EMP_ID));
c.addAll(Arrays.asList(
EMP_SAL.EMP_ID,
EMP_SAL.SALARY
));
}
Result<?> result =
ctx.select(c)
.from(t)
.fetch();
Speaking directly to the syntax errors:
The parentheses in this statement are invalid. Removing them will solve the problem.
The table Employee is used twice in the FROM clause. You must alias the tables for this to work.
Select dbo.Employee.Dept_ID,dbo.Employee.Emp_ID,
dbo.Employee.Emp_Name,dbo.Employee_DataVal.DeptNo,
dbo.Employee_DataVal.EmpName,dbo.Employee_DataVal.EmpNo
,dbo.Emp_Sal.Emp_ID,dbo.Emp_Sal.Salary
FROM Employee e1 INNER JOIN Employee_DataVal
ON e1.Emp_ID = Employee_DataVal.EmpNo
AND e1.Dept_ID = Employee_DataVal.DeptNo
LEFT JOIN Employee e2
ON Employee_DataVal.EmpName = e2.Emp_Name
Speaking to your broader question, the concept of a generic SQL query generator is quite common and has had several implementation. You won't find full implementation guidance in a forum such as this.
Cheers!
You are using LEFT Join same as the Self join. which is actually creating the problem.
In first case error is coming because of the wrong ) in wrong place as pointed below; Which making the end of query and so LEFT JOIN throwing an error. the ) must be at end of the query.
FROM Employee
INNER JOIN Employee_DataVal
ON Employee.Dept_ID = Employee_DataVal.DeptNo
OR Employee_DataVal.EmpName = Employee.Emp_Name ) <--Here
LEFT JOIN Emp_Sal
In second case, you are trying to do a self join to the same table in that case as the error already suggested you, you need to use correlation names like
FROM Employee emp1 <-- Here used a table alias emp1
INNER JOIN Employee_DataVal ed
ON emp1.Emp_ID = ed.EmpNo
AND emp.Dept_ID = ed.DeptNo
LEFT JOIN Employee emp2 <-- Here used a different table alias emp2
ON ed.EmpName = emp2.Emp_Name
Moreover, the LEFT JOIN Employee won't make any sense here and which can simply be modified to below code
FROM Employee emp1
INNER JOIN Employee_DataVal ed
ON emp1.Emp_ID = ed.EmpNo
AND emp.Dept_ID = ed.DeptNo
AND emp.Emp_Name = ed.EmpName <-- here by adding another join condition