I have PL/SQL query with old style joins (with using (+) ). And now I need to add left joined table with REGEXP_LIKE clause. How can I make this?
In ANSI-style the query look like this:
select
*
from
deals d
left join
auctions a on a.session_code = d.session_code
left join
auction_history ah on ah.auction_code = a.auction_code and
REGEXP_LIKE(ah.auction_code, '^[A-Z]+')
where
trunc(d.operday) = trunc(sysdate)
And in old style I want to get something like this:
select
*
from
deals d,
auctions a,
auction_history ah,
where
trunc(d.operday) = trunc(sysdate) and
d.session_code = a.session_code (+) and
(a.auction_code = ah.auction_code (+) and
REGEXP_LIKE(ah.auction_code, '^[A-Z]+'))
But it doesn't return deals which session_code is null.
Thanks in advance!
REGEXP_LIKE is treated as a regular function regarding legacy joins. Here's an example:
SQL> WITH main_table AS
2 (SELECT 1 ID FROM dual UNION ALL
3 SELECT 2 FROM dual),
4 lookup_table AS
5 (SELECT 1 ID, 'txt' txt FROM dual UNION ALL
6 SELECT 2 ID, '999' txt FROM dual)
7 SELECT m.id, l.txt
8 FROM main_table m, lookup_table l
9 WHERE m.id = l.id(+)
10 AND REGEXP_LIKE(l.txt(+), '^[A-Z]+');
ID TXT
---------- ---
1 txt
2
Still, I would advise against using old-style joins in recent editions.
Related
I have a little problem, my query look like this
select count(A.toto)
from B
inner join C
on B.tata = C.tata
inner join A
on C.tutu = A.tutu
group by A.toto, A.zaza, A.zozo;
and my result look like this :
1
2
1
6
7
4
1
1
1
But I want only the number of rows, for this example, the value that I would like to have is 9.
But I don't know how I can have this value...
Thank you in advance !!
You can use count(distinct). Unfortunately, Oracle doesn't support count(distinct) with multiple arguments, so a typical method is just to concatenate the value together:
select count(distinct A.toto || ':' || A.zaza || ':' || A.zozo)
from B inner join
C
on B.tata = C.tata inner join
A
on C.tutu = A.tutu;
This assumes that. the column values don't have the separator character (or at least in such a way that the concatenation is the same for rows with different key values).
An alternative method is to use a subquery:
select count(*)
from (select 1
from B inner join
C
on B.tata = C.tata inner join
A
on C.tutu = A.tutu
group by A.toto, A.zaza, A.zozo
) abc
Going to use this query as a subquery, the problem is it returns many rows of duplicates. Tried to use COUNT() instead of exists, but it still returns a multiple answer.
Every table can only contain one record of superRef.
The below query I`ll use in SELECT col_a, [the CASE] From MyTable
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = myTable.sysno AND A_specAttr = 'value')
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo WHERE C_superRef = myTable.sysno AND b_type = 2)
THEN 2
ELSE (SELECT C_intType FROM C
WHERE C_superRef = myTable.sysno)
END
FROM A, B, C
result:
3
3
3
3
3
3...
What if you did this? Because Im guessing you are getting an implicit full outer join A X B X C then running the case statement for each row in that result set.
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM ( SELECT COUNT(*) FROM A ) --This is a hack but should work in ANSI sql.
--Your milage my vary with different RDBMS flavors.
DUAL is what I needed, thanks to Thorsten Kettner
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM DUAL
I want to find where mydata has a Q value but not at least one corresponding d value. How would I solve using a left join or right join?
If it can not be solved using joins, please give some insight into why not, because I am not seeing it.
Below is the solution that I found which works against data provided.
SELECT distinct tablea.mykey
FROM mytest as tablea
where tablea.mydata = 'Q'
and tablea.mykey not in (select distinct tableb.mykey
FROM mytest as tableb
where tableb.mydata = 'd')
mykey mydata
7 d
5 Q
5 d
5 d
6 Q
6 d
6 a
9 Q
9 a
9 a
You can use an outer join and then select only the non-matches
SELECT distinct tablea.mykey
FROM mytest as a
left join mytest as b on a.mykey = b.mykey
and b.mydata = 'd'
where a.mydata = 'Q'
and b.mykey is null
I am using SQL Server 2012. Can anyone tell me where i am going wrong ?
SELECT
avg ( tbl.FirstBillComplete )
FROM
( select l.MONTH, a.OverallScore, (a.FirstBillComplete), ( a.EmailComplete)
from tbl_T1 a join calls.dbo.c1_LP l on a.QID = l.QID
union
select l.MONTH, a.OverallScore, (a.FirstBillComplete), ( a.EmailComplete)
from tbl_2 a join calls.dbo.C3_LP l on a.QID = l.QID
union ALL
select l.MONTH, a.OverallScore, (a.FirstBillComplete), ( a.EmailComplete)
from tbl_3 a join c2 l on a.QID = l.QID
) As tbl
GROUP BY tbl.MONTH
The error I get is :
No column was specified for column 7 of 'tbl'.
No column was specified for column 8 of 'tbl'
You need to specify a column name for column 7 and 8 of tbl: use
'' AS MyColumn7,
For example.
I need a help on sql database side. And i have
table 1 : ENTITY_TYPE
entity_type_id entity_name
1 Task
2 Page
3 Project
4 Message
5 User
and table 2 : MESSAGE , that contains message from each entity values like
message_id entity_type owner_tableid message
1 1 12 A message on task level
2 3 14 A message on project level
and I want select these message according to each entity type and details from its owner table using 'owner_tableid' ie a query like....
select * from MESSAGE JOIN
case entity_type when 1 then taskTable
when 2 then pageTable
when 3 then projectTable
when 4 then MessageTable
when 5 then UserTable
Which is best method to solve this issue on single procedure. Any idea ?? Now I am using IF clause for each entity...
You can't parameterise the tables involved in a query (so you can't put a table name in a variable and expect that to be used either).
One way to do it is as a chain of left joins:
select
* /* TODO - Pick columns */
from
MESSAGE m
left join
taskTable tt
on
m.entity_type = 1 and
m.owner_entity_id = tt.id
left join
pageTable pt
on
m.entity_type = 2 and
m.owner_entity_id = pt.id
left join
projectTable prt
on
m.entity_type = 3 and
m.owner_entity_id = prt.id
left join
MessageTable mt
on
m.entity_type = 4 and
m.owner_entity_id = mt.id
left join
UserTable ut
on
m.entity_type = 5 and
m.owner_entity_id = ut.id
If you want values from these tables to appear in a single column in the result, use a COALESCE across all of the values, e.g.
COALESCE(tt.Value,pt.Value,prt.Value,mt.Value,ut.Value) as Value
Use Union Clause with your individual entity_type
SELECT * FROM Message
JOIN pageTable ON ....
WHERE entity_type = 1
UNION ALL
..........
entity_type = 2
UNION ALL
..........
entity_type = 3
Select ...
From Message
Join (
Select 1 As entity_type, id
From taskTable
Union All
Select 2, id
From pageTable
Union All
Select 3, id
From projectTable
Union All
Select 4, id
From messageTable
Union All
Select 5, id
From userTable
) As Z
On Z.entity_type = Message.entity_type
And Z.id = Message.owner_tableid
If you need to return several entity_types details in one query, than UNION might help:
SELECT interesting_columns FROM Message
JOIN pageTable ON (joinPredicate)
WHERE entity_type = 1
UNION ALL
SELECT interesting_columns FROM Message
JOIN pageTable ON (joinPredicate)
WHERE entity_type = 2
-- ...
But if you only need details of certain entity_type than you original solution with IF would be much better.