how to join all the tables without using any condition - oracle11g

all the below results are not related to each other wheras we cannot use any condition.
ID
----------
1
2
3
4
5
6
7
7 rows selected.
NAME
-----------------
SRUJAN
DEERAJ
VINEETH
CHANIKYA
LAVANYA
KAVITHA
BUNNY
7 rows selected.
AGE
----------
23
24
26
25
29
28
24
7 rows selected.
ADDRESS
-------------
NAGARAM
BANDLAGUDA
UPPAL
KUKATPALLY
HB COLONY
MOULALI
BOUDHA NAGAR
7 rows selected.
SALARY
----------
12000
13000
14000
15000
16000
17000
18000
7 rows selected.
I USED
SQL>select id,name,age,address,salary from table1,table2,table3,table4,table5;
but it showing 16807 rows selected
i want to get only one table.
please suggest a query.

The only possible join between 2 tables having only 1 columns and both having no relation is cross join. You cannot avoid it. And the same you are getting when you tried to join. The best way for you is to create a sequence as ID and then call it in your select statement of table2.
CREATE SEQUENCE TEST_SEQ
START WITH 1
MAXVALUE 9999999999999999999999999999
MINVALUE 1
NOCYCLE;
select TEST_SEQ.nextval ID,col1 NAME
from table2;

Here is one way, using inner joins. This solution matches the lowest id with the first name in alphabetical order, the lowest age, etc.
If instead of this ordered matching you need random matching, that is easy to do as well: in the over... clause of the prep tables, change the order by clause to order by dbms_random.value() (in all places).
In the solution below I use only the first three tables, but the same works for any number of input tables.
with
tbl_id ( id ) as (
select 1 from dual union all
select 2 from dual union all
select 3 from dual union all
select 4 from dual union all
select 5 from dual union all
select 6 from dual union all
select 7 from dual
),
tbl_name ( name ) as (
select 'SRUJAN' from dual union all
select 'DEERAJ' from dual union all
select 'VINEETH' from dual union all
select 'CHANIKYA' from dual union all
select 'LAVANYA' from dual union all
select 'KAVITHA' from dual union all
select 'BUNNY' from dual
),
tbl_age ( age ) as (
select 23 from dual union all
select 24 from dual union all
select 26 from dual union all
select 25 from dual union all
select 29 from dual union all
select 28 from dual union all
select 24 from dual
),
prep_id ( id, rn ) as (
select id, row_number() over (order by id) from tbl_id
),
prep_name ( name, rn ) as (
select name, row_number() over (order by name) from tbl_name
),
prep_age ( age , rn ) as (
select age, row_number() over (order by age) from tbl_age
)
select i.id, n.name, a.age
from prep_id i inner join prep_name n on i.rn = n.rn
inner join prep_age a on i.rn = a.rn
;
Output:
ID NAME AGE
---------- -------- ----------
1 BUNNY 23
2 CHANIKYA 24
3 DEERAJ 24
4 KAVITHA 25
5 LAVANYA 26
6 SRUJAN 28
7 VINEETH 29
7 rows selected

Related

Is a recursive query possible?

An Oracle SQL question that seems simple to me, but I just can't do it (without manually making several successive queries)... I would like to use a SQL "recursive" approach or any other method that would avoid me to manually use "n" times the same query.
Here is a very simplified example of my data:
row
ID
Value
Result
1
135
AAA
AAA
2
246
BBB
BBB
3
357
135
AAA
4
468
357
AAA
5
578
EEE
EEE
If a value refers to an ID, then we need to fetch the value of that ID. If the value of an ID is another ID, then you have to keep looking for an "true" value. If the value is not an ID, then we can take it directly.
The column "Result" gives the expected result:
For the row 3, you have to look for the value of the ID 135.
For the line 4, you have to get the value of the ID 357, which corresponds to the value of the ID 135.
Here, what I don't want to do:
with my_data as(
select '135' as id, 'AAA' as value from dual union all
select '246', 'BBB' from dual union all
select '357', '135' from dual union all
select '468', '357' from dual union all
select '578', 'EEE' from dual
)
,step as(
select d1.*
,nvl((select d2.value from my_data d2 where d1.value=d2.id),d1.value) as step_1
from my_data d1
)
-- steps to do again and again...
select step.*
,nvl((select my_data.value from my_data where step.step_1=my_data.id),step.step_1) as step_n
from step
order by 1
;
Thank you for your help.
In addition to Carlos S anwser:
It does exactly what I want in my "very simplified" example. However, with a sub-set of real data, there is something wrong (a little too much data). On the other hand, if I remove the results that refer to IDs, it gives exactly what I want. I can't find the problem.
Note: as shown in my initial example, IDs will always start with a number and a "real" value will always start with a letter. So the regex strategy is "ok".
Here is a real example:
with my_data as(
select '116554226_2' as id, '116554226_1' as value from dual union all
select '119675285_2' as id, '119675285_1' as value from dual union all
select '119675285_3' as id, '119675285_2' as value from dual union all
select '13656777_1' as id, '119675471_1' as value from dual union all
select '13656777_5001' as id, '119675471_1' as value from dual union all
select '13656777_2' as id, '13656777_1' as value from dual union all
select '13656155_1' as id, '13657581_1' as value from dual union all
select '13657581_2' as id, '13657581_1' as value from dual union all
select '13657015_1' as id, '13657759_1' as value from dual union all
select '13657759_2' as id, '13657759_1' as value from dual union all
select '116554226_1' as id, '471502681_1' as value from dual union all
select '462721769_1' as id, 'O7X5J' as value from dual union all
select '471502681_1' as id, 'T3L8L' as value from dual union all
select '119675471_1' as id, 'T8Q0G' as value from dual union all
select '119675471_5001' as id, 'T8Q0G' as value from dual union all
select '116555133_1' as id, 'T9J2Q' as value from dual union all
select '13657581_1' as id, 'U5H5Z' as value from dual union all
select '119674049_1' as id, 'Y5G7V' as value from dual union all
select '13657759_1' as id, 'Z0Y9C' as value from dual union all
select '119675285_1' as id, 'Z7E0D' as value from dual
)
SELECT my_data.*, CONNECT_BY_ROOT value result
FROM my_data
CONNECT BY PRIOR id = value
START WITH REGEXP_LIKE(value,'[^0-9]')
;
The boxed data is unwanted, otherwise everything below it is ok.
I think this query may help you:
with my_data as(
select '135' as id, 'AAA' as value from dual union all
select '246', 'BBB' from dual union all
select '357', '135' from dual union all
select '468', '357' from dual union all
select '578', 'EEE' from dual
)
SELECT rownum, id, value, CONNECT_BY_ROOT value result
FROM my_data
CONNECT BY PRIOR id = value
START WITH REGEXP_LIKE(value,'[^0-9]')
ROWNUM
ID
VALUE
RESULT
1
135
AAA
AAA
2
357
135
AAA
3
468
357
AAA
4
246
BBB
BBB
5
578
EEE
EEE

Display records not matching in where clause

I need to display records not matching the where clause.
Example - select * from citytable where city in ('aa','bb','cc', 'dd','ee');
only aa, bb, cc are present in table, dd & ee are not present in the table. However, I still need to display dd & ee.
You are probably looking for something like this. An IN condition is the same as an inner join to a table containing the unique (distinct) values from the IN list. What you want is an outer join. You need to have a table instead of the IN list. In the solution below I show how you can create this "helper" table on the fly; there are several other methods, this just demonstrates the idea.
select deptno, ename from emp where deptno in (10, 50, 80);
DEPTNO ENAME
------ ------
10 CLARK
10 KING
10 MILLER
with h ( deptno ) as (
select 10 from dual union all
select 50 from dual union all
select 80 from dual
)
select h.deptno, e.ename
from h left outer join emp e
on h.deptno = e.deptno
;
DEPTNO ENAME
------ ------
10 CLARK
10 KING
10 MILLER
50
80
I'm not sure exactly how you want the output to look. If there is no data where city='ee', what exactly do you want to show? Something like this?
SELECT * FROM
(SELECT key AS A_key, one AS A_one, two AS A_two FROM cityTable WHERE one='aa') AS A
JOIN
(SELECT key AS E_key, one AS E_one, two AS E_two FROM cityTable WHERE one='ee') AS E
ON A_key=E_key
...etc.
Edit: or maybe this is it:
SELECT city FROM (SELECT city, count(*) AS c FROM cityTable GROUP BY city) WHERE c = 0
As i understand you said the 'dd' amd 'ee' are not present in the table but you still need it so you can achieve it using a union all. But remember that the columns of the 'dd' and 'ee' rows will always be null since there is no records present in your citytable
SELECT ct.col1 AS city, ct.col2.....<all columns of your table>
from citytable ct
where city in ('aa','bb','cc')
UNION ALL
select 'dd' as city,null ,null.....<nulls as many times as the number of columns of your table>
from citytable ct1
UNION ALL
select 'ee' as city,null ,null.....<nulls as many times as the number of columns of your table>
from citytable ct2

Group by not returning 0 value

My table contains pk_id,reviewer_id,rating.
There are 4 type of rating.
1-very good.
2-good.
3-bad.
4-very bad.
I want to calculate how much rating given by each reviewer.
Means:
If Akee having id 200 has given 2 very good,4 good,3 bad and zero very bad rating to different code.
I want result
count--- rate
2---------1
4---------2
3---------3
0---------4
My query is
SELECT COUNT(RATE),RATE
FROM CODE_REVIEW WHERE CODE_REVIEWER_ID= 200
GROUP BY RATE;
It is showing result
count--- rate
2---------1
4---------2
3---------3
I want to show the fourth row that is 4 rating zero.
How can it be done??
If Rate is not the primary key in another table then you need define your own list of rates so MySQL knows what the permutations of rate are:
SELECT Rates.Rate,
COUNT(Code_Review.Rate) AS CountOfRate
FROM ( SELECT 1 AS Rate UNION ALL
SELECT 2 AS Rate UNION ALL
SELECT 3 AS Rate UNION ALL
SELECT 4
) AS Rates
LEFT JOIN Code_Review
ON Code_Review.Rate = Rates.Rate
AND CODE_REVIEWER_ID = 200
GROUP BY Rates.Rate
Try this query:
SELECT coalesce(c.cnt, 0), r.rate
FROM (SELECT 1 AS rate UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4) AS r
LEFT JOIN (SELECT COUNT(RATE),RATE
FROM CODE_REVIEW WHERE CODE_REVIEWER_ID= 200
GROUP BY RATE) AS c
ON r.rate = c.rate;
The first subquery creates a list of possible rates. You can avoid it if you have a table which defines all rates;
Second subquery is yours;
LEFT JOIN guarantees that all rates will be shown;
coalesce() is needed to convert NULL into 0.
Assuming that you do not have a separate table where the rates are defined.
SElECT * from (
SELECT distinct(m.rate), countrate from code_review m
LEFT JOIN
(SELECT COUNT(rate) as countrate,rate FROM code_review
WHERE code_reviewer_id=200 GROUP BY rate) t
ON m.rate=t.rate) a
You could do it somthing like this
SELECT
rates.RATE
, SUM(COUNT) COUNT
FROM
(
SELECT 1 RATE, 0 COUNT UNION ALL
SELECT 2 RATE, 0 COUNT UNION ALL
SELECT 3 RATE, 0 COUNT UNION ALL
SELECT 4 RATE, 0 COUNT
) Rates
LEFT JOIN
(
SELECT
RATE
, COUNT(RATE) COUNT
FROM
CODE_REVIEW
WHERE
CODE_REVIEWER_ID= 200
GROUP BY RATE
) Ratings200
ON Ratings200.RATE = Rates.RATE
If you can, you should push to try to get it in column format as it is simple as:
SELECT
SUM(rate = 1) AS 1,
SUM(rate = 2) AS 2,
SUM(rate = 3) AS 3,
SUM(rate = 4) AS 4
FROM
code_review
WHERE
code_reviewer_id = 200
But if you really need a row format, you could do:
SELECT
a.rate,
COUNT(b.rate) AS cnt
FROM
(
SELECT 1 AS rate UNION ALL
SELECT 2 AS rate UNION ALL
SELECT 3 AS rate UNION ALL
SELECT 4 AS rate
) a
LEFT JOIN
code_review b ON a.rate = b.rate AND code_reviewer_id = 200
GROUP BY
a.rate
SELECT
Rate,
totCount
FROM
(
Select
Rate,
count(Rate) as totCount
from
Code_Review
where
CODE_REVIEWER_ID = 200
group by
Rate
union
select 4, 0
union
select 3, 0
union
select 2, 0
union
select 1, 0
) AS T
group by
T.Rate

using vb6 and oracle

I have the records using the query
SELECT trunc(createdon,'hh') CREATEDON,count(*)
FROM WHERE LABSTATUS=1 AND
CREATEDON >=TO_DATE('01/07/2010 10','DD/MM/YYYY hh')
GROUP BY trunc(createdon,'hh')
in an hourly basis.. I need to place the count value in corresponding time column in the grid.
How can I do?? any idea
You can do it like this:
Hours are in columns
SELECT TRUNC(createdon,'hh'), SUM(CASE WHEN hh=1 THEN 1 ELSE 0) h1,
SUM(CASE WHEN hh=2 THEN 1 ELSE 0) h2 .....
FROM TABLle1,
(SELECT 1 AS hh FROM dual
UNION
SELECT 2 AS hh FROM dual
UNION
SELECT 3 AS hh FROM dual
....
) hours
WHERE LABSTATUS=1 AND CREATEDON >=TO_DATE('01/07/2010 10','DD/MM/YYYY hh') AND
TRUNC(createdon,'hh')= hours.hh
GROUP BY TRUNC(createdon,'hh')
Hours are in rows:
SELECT hours.hh, SUM(CASE WHEN TRUNC(createdon,'hh')= hours.hh THEN 1 ELSE 0 END) hh,
FROM TABLle1,
(SELECT 1 AS hh FROM dual
UNION
SELECT 2 AS hh FROM dual
UNION
SELECT 3 AS hh FROM dual
....
) hours
WHERE LABSTATUS=1 AND CREATEDON >=TO_DATE('01/07/2010 10','DD/MM/YYYY hh')
GROUP BY hours.hh
This query will result like this
row 1 12
row 2 0
row 3 4
...

Select numbers between a range (1 to 100) in sqlite

I know some of the solutions in SQL but couldn't find any of them from SQlite.
I just want to execute a select query that returns a resultset of numbers ranging from 1 to 100.
Numbers
1
2
3
4
......
5
A correction: I don't actually have a table at all. (however a solution is encouraged with a virtual table like dual in MySQL)
Thanks sgmentzer!
Inspired by your answer I went ahead and also found this:
WITH RECURSIVE
cnt(x) AS (
SELECT 1
UNION ALL
SELECT x+1 FROM cnt
LIMIT 100000
)
SELECT x FROM cnt;
How about
SELECT * FROM myTable WHERE myNumber >= 1 AND myNumber <= 100;
?
Example subquery to generate the series 1 <= n <= 100000 in SQLite. No table is created or used.
select 1+e+d*10+c*100+b*1000+a*10000 as n from
(select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9),
(select 0 as b union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9),
(select 0 as c union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9),
(select 0 as d union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9),
(select 0 as e union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9);
I don't think SQLite has a clean way to do this, so you'll need to use a virtual table interface. SQLite ships one for 'C', and apsw has one for python as I'll demonstrate below. Here's documentation for the APSW Virtual Table interface.
#!/usr/bin/python
import apsw,tempfile
### Opening/creating database
filename=tempfile.mktemp() #insecure - do not use in production code
connection=apsw.Connection(filename)
cursor=connection.cursor()
# This gets registered with the Connection
class Source:
def Create(self, db, modulename, dbname, tablename, *args):
schema="create table foo( dummy integer )"
return schema,Table()
Connect=Create
# Represents a table
class Table:
def __init__(self):
pass
def BestIndex(self, constraints, orderbys):
used = []
self.constraints = []
ucount = 0
for c in constraints:
if c[1] in (
apsw.SQLITE_INDEX_CONSTRAINT_GT,
apsw.SQLITE_INDEX_CONSTRAINT_GE,
apsw.SQLITE_INDEX_CONSTRAINT_LT,
apsw.SQLITE_INDEX_CONSTRAINT_LE,
apsw.SQLITE_INDEX_CONSTRAINT_EQ,
):
used.append( ucount ) #tell sqlite we want to use this one
self.constraints.append( c[1] ) #save some for later
else:
used.append( None ) #skip anything we don't understand
ucount += 1
return ( used, # used constraints list
0, # index number - no biggie we only support one right now
)
def Open(self):
return Cursor(self)
def Disconnect(self):
pass
Destroy=Disconnect
# Represents a cursor
class Cursor:
def __init__(self, table):
self.table=table
def Filter(self, indexnum, indexname, constraintargs):
start = 0
self.end = 4000000000
#map constraint arguments to start and end of generation
for tc, ca in zip( self.table.constraints, constraintargs ):
if tc == apsw.SQLITE_INDEX_CONSTRAINT_EQ:
start = ca
self.end = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_LE:
if self.end > ca:
self.end = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_LT:
if self.end >= ca:
self.end = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_GE:
if start < ca:
start = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_GT:
if start >= ca:
start = ca
self.pos = start
def Eof(self):
return self.pos > self.end
def Rowid(self):
return self.pos
def Next(self):
self.pos+=1
def Close(self):
pass
# Register the module as intsource, you can make a bunch if needed
connection.createmodule("intsource", Source())
# Create virtual table to use intsource
cursor.execute("create virtual table uints using intsource()")
# Do some counting
for i in cursor.execute("SELECT rowid FROM uints WHERE rowid BETWEEN 1 AND 100"):
print i
This implements a virtual-table type named "intsource", which by default counts from 0 to 4*10^9. It supports directly filtering by equality and comparison, but any other constraints will still be filtered out by sqlite. Virtual tables are a very powerful concept you can do a lot with, this is probably one of the simplest uses for them. Also, thank you for a good excuse to try out a new virtual table API.
SELECT * FROM Numbers limit 1, 100;
If your goal is to select actual records from a table with values between 1 and 100, use BETWEEN as shown by the other respondents.
If your goal is to generate a sequence of numbers from 1 to 100 without having a table to base it on, I don't believe SQLite has a feature that does this.
SELECT * FROM myTable WHERE myNumber BETWEEN 1 AND 100;
This is more efficient than using 2 WHERE clauses.

Resources