Is CASE statement allowed in join? Is there a good way to accomplish the task here? My real query has some other left join.
I would like to join T1 and T2 in this condition:
1. when T1.sub_service is not null, then join with T2.type
2. when T1.sub_service is null, then use T1.service to join with T2.type
SELECT T1.service, T1.sub_service, T2.type
FROM TABLE1 T1
LEFT JOIN TABLE2 T2
ON T2.type LIKE
CASE WHEN T1.sub_service IS NULL THEN T1.service
WHEN T1.sub_service IS NOT NULL THEN T1.sub_service
END
Simply replace the LIKE with =:
ON T2.type =
CASE WHEN T1.sub_service IS NULL THEN T1.service
WHEN T1.sub_service IS NOT NULL THEN T1.sub_service
END
But you can further simplify this to a COALESCE:
ON T2.type = COALESCE(T1.sub_service, T1.service)
Related
I need Only one unique result from tableB.Field to tableA.Field
I am using sdo operator sdo_nn, this is the code:
UPDATE table1 t1
SET t1.fieldA = (SELECT T2.fieldB,SDO_NN_DISTANCE(1) distance
FROM table1 T1, table2 T2
WHERE
(sdo_nn(t1.geometry,t2.geometry,'SDO_NUM_RES=1',1)= 'TRUE')
ORDER BY DIST
)
WHERE EXISTS(
SELECT 1
FROM table2 t2
WHERE sdo_nn(t1.geometry, t2.geometry,'SDO_NUM_RES=1',1)='TRUE'
AND(t2.cell_name = 'string1' or t2.cell_name = string2')AND t1.fieldA = NULL
);
In the select sentence of the subquery i get an error because i only use one field(t1.fieldA), but in the sentence i use the operator SDO_NN_DISTANCE(1) and the sql developer count this operator like another field. What is the correct way to write this sentence? I only use sql because i need to insert this code in vba
Thanks!!!
Obviously, you can't (simplified)
set t1.fieldA = (t2.fieldB, distance) --> you want to put two values into a single column
Therefore, get fieldB alone from the subquery which uses analytic function (row_number) to "sort" rows by sdo_nn_distance(1) desc; then get the first row's fieldB value.
Something like this (I hope I set the parenthesis right):
UPDATE table1 t1
SET t1.fieldA =
(SELECT x.fieldB --> only fieldB
FROM (SELECT T2.fieldB, --> from your subquery
SDO_NN_DISTANCE (1) distance,
ROW_NUMBER ()
OVER (ORDER BY sdo_nn_distance (1) DESC) rn
FROM table1 T1, table2 T2
WHERE (sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE')) x
WHERE rn = 1) --> where RN = 1
WHERE EXISTS
(SELECT 1
FROM table2 t2
WHERE sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE'
AND ( t2.cell_name = 'string1'
OR t2.cell_name = 'string2')
AND t1.fieldA IS NULL);
I'm trying to get the result into a variable (is it possible to do it as a %rowtype of an existing table? probably not because of conflicting columns) where it would display me all the values where the two refs overlap and the i_ref(which is inputted ) also overlaps with the ref from t1.
select *
into aRow
from table1 t1
where t1.ref = i_ref
and (select * from table2 t2 where t1.ref = t2.ref);
What am I doing wrong with my select?
You can join tables instead of nested subquery:
select t1.*
into aRow
from table1 t1 join table2 t2 on t1.ref = t2.ref
where t1.ref = i_ref
I have a below working query:
`select distinct t1.ExNo,
t3.ExDesc from table1 t1
left join table2 t2 on t1.ExNo = t2.ExNo
join table3 t3 on t3.ExTyp = case
when t1.ExTyp = 'CONT'
and t2.ExTyp is not null
then t2.ExTyp
else t1.ExTyp
end
order by t1.ExNo;`
But if the same query modified as below and use, I am getting this error. Could you please rectify:
`select distinct t1.ExNo,
t3.ExDesc
from table1 t1 t1, table2 t2,table3 t3 where
t1.ExNo *= t2.ExNo and
t3.ExTyp = case
when t1.ExTyp = 'CONTNR'
and t2.ExTyp is not null
then t2.ExTyp
else t1.ExTyp
end
order by t1.ExNo;`
Error:
The table is an inner member of an outer-join clause. This is not allowed if the table also participates in a regular join clause.
I have a requirement below to choose latest status.
Table 1:
Table2:
Results Expected:
Below is the logic we need.
SELECT
Table1.ID,
,CASE WHEN (Table1.hub=Table2.hub) THEN Table2.Status ELSE NULL END AS Original_Status
,CASE WHEN (Table1.hub<>Table2.hub AND Table2.Status like 'Found%' ) THEN Table2.hub ELSE NULL END AS Derived_Hub
,CASE WHEN (Table1.hub<>Table2.hub AND Table2.Status like 'Found%' ) THEN Table2.Status ELSE NULL END AS Derived_Status
from
Table1
Join Table2
ON (Table1.ID=Table2.ID)
With this code, I am getting 3 rows. If I put max in the above case statements, I am getting Hub3 instead of Hub2.
Could you please let me know how I can merge everything into single row. Please note that I want to show latest found Status from Table 2 even if there are 2 hubs with found status.
Let me know if you need any further information.
I think your best bet is to join into Table 2 twice. The first time, much like you are doing here, but using a LEFT OUTER JOIN on both id and hub. Then the second time on a derived version of table2 where you only select the top 1 records when sorted by timestamp in descending order:
SELECT
t1.id,
t1.hub as "Original Hub"
t2.status as "Original Hub Status",
t3.hub as "Found Hub",
t3.status as "Found Hub Status"
FROM
Table1 t1
LEFT OUTER JOIN Table2 t2 ON
t1.id = t2.id AND
t1.hub = t2.hub
LEFT OUTER JOIN
(
--Select a hub with the same id, that doesn't share the same hub number
--Only choose the top record when sorted by timestamp in descending order
SELECT TOP 1 id, hub, status
FROM table2
WHERE t1.hub <> table2.hub
ORDER BY TimeStamp Desc
) t3 ON
t1.id = t3.id
That subquery that has alias t3 is using a correlated subquery by referencing the t1.hub value in it's WHERE statement.
In TD14.10 you can utilize LAST_VALUE to access data from the "last" row. The CASEs are based on your query:
SELECT
t2.ID,
CASE WHEN t1.Hub = t2.Hub THEN t2.Hub END AS Original_Hub,
CASE WHEN t1.Hub = t2.Hub THEN t2.Status END AS Original_Status,
-- get the last Hub
LAST_VALUE(CASE WHEN t1.Hub <> t2.Hub AND Table2.Status like 'Found%'
THEN t2.Hub
END)
OVER (PARTITION BY t1.ID
ORDER BY CASE WHEN t1.Hub = t2.Hub THEN 0 ELSE 1 END, t2.TS
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS Derived_Hub,
-- get the last Status
LAST_VALUE(CASE WHEN t1.Hub <> t2.Hub AND Table2.Status like 'Found%'
THEN t2.Status
END)
OVER (PARTITION BY t1.ID
ORDER BY CASE WHEN t1.Hub = t2.Hub THEN 0 ELSE 1 END, t2.TS
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS Derived_Status
FROM
Table1 AS t1
JOIN Table2 AS t2
ON (t1.ID=t2.ID)
QUALIFY
ROW_NUMBER () -- return the 1st row only
OVER (PARTITION BY t1.ID
ORDER BY CASE WHEN t1.Hub = t2.Hub THEN 0 ELSE 1 END, t2.TS) = 1
EXPLAIN should combine all OVER into a single STATS-step as they use the same PARTITION BY and ORDER BY.
My scenario is this:
I have a table with a structure like this (simplified) -
CREATE TABLE [dbo].[pe_mem](
[pm_member] [int] NULL,
[pm_surname] [char](50) NULL,
[pm_forename] [char](50) NULL,
[pm_rsi_num] [char](11) NULL
) ON [PRIMARY]
I need to run a query to find all rows that have an identical pm_rsi_num but a different pm_surname.
Can anyone help me out with this?
Thanks!
You can use a self join for that:
select *
from pe_mem t1
join pe_mem t2
on t1.pm_rsi_num = t2.pm_rsi_num
and t1.pm_surname <> t2.pm_surname
Exists variant:
select *
from pe_mem t1
where exists
(select null
from pe_mem t2
where t1.pm_rsi_num = t2.pm_rsi_num
and t1.pm_surname <> t2.pm_surname)
Single table scan version:
select pm_rsi_num
from pe_mem
group by pm_rsi_num
having count(distinct pm_surname) > 1
Just join the table back on itself and use your criteria as the join criteria:
select * from pe_mem as p1
inner join pe_mem as p2
on p1.pm_rsi_num = p2.pm_rsi_num
and p1.pm_surname <> p2.pm_surname