Apply a Substr to a distinct result in oracle - sql

In Oracle, I need to do the average of a column (timeInmillis) from a join query that shows "duplicated" values (relative to the timeInmillis column from table1). I need to mantain the values from the join, but get the right result for the average.
I'm trying to do something like this:
select AVG(SUBSTR(DISTINCT(concat(id1,timeInMillis)),LENGTH(id1)+1,LENGTH(CONCAT(id1,timeInMillis)))), someColumn, otherColumn
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id1 = t2.id1 group by somestuff,someotherStuff;
If I try to do this, I get:
ORA-00936: missing expression
This would be an example:
Table1:
id1 timeInMillis otherColumn
1 5 X
2 15 X
Table2:
id2 id1 otherColumn
--------------------
1 1 X
2 1 X
3 2 X
From my join I get a resultset like this:
id1 id2 timeInmillis moreColumns
--------------------------------
1 1 5 X
1 2 5 X
2 3 15 X
I need to get the average of 5 and 15 (with distinct id1), but I can't modify the where part of the sql (cause of the other values I'm getting)
My result should be:
AVG(TIMEINMILLIS) otherResults
----------------------------------
10 'whatever'
Thanks in advance.

1) Option
select SUBSTR(someColumn,n,m) from (
select DISTINCT someColumn from MYTABLE
);
2) Option
select DISTINCT SUBSTR(someColumn,n,m) from MYTABLE;
*) Queries can return different result.

Your last edit finally explains clearly what you want. You want one line only, showing the avarage of table1's values, but of course without the duplicates that you got because of joining with table 2.
One solution is to get to the final value in two steps:
select avg(distinct_time), sum(sub_sum)
from
(
select max(timeinmillis) as distinct_time, sum(some_other_colum) as sub_sum
from (query)
group by id1
);
The other solution would be to rewrite the query.

Your syntax is wrong. You can try somthing like this either:-
select avg(TimeInMillis), other_cols_as_well
from(SELECT TAB1.id1, TAB2.id2, avg(TimeInMillis) as TimeInMillis
FROM TAB1, TAB2
WHERE TAB1.id1 = TAB2.id1
group by TAB1.id1, TAB2.id2) temp
where temp.id1 <> temp.id2
group by other_cols_as_well
Here is the fiddle
http://sqlfiddle.com/#!4/1fc017/16

Related

how to set a range of defaults in a count query

I have a simple table of values:
column1
-------
2
5
7
5
8
7
and this simple query of number count:
SELECT column1, count(column1) as counter
FROM table
GROUP BY column1
ORDER BY count(column1) DESC
The question how can I add rows with values 0 when I have a number range for example from 1 to 8.
I want to get the result like this:
column1 Counter
-------- -------
5 2
7 2
2 1
8 1
1 0 <-- Row Add
2 0 <-- Row Add
3 0 <-- Row Add
4 0 <-- Row Add
6 0 <-- Row Add
Thanks very much.
If you are willing to use more than 1 query and to put your range of numbers in a table at least temporarily then you can do this with a full outer join. To do a Full outer join in access you combine a left join and a right join using either UNION OR UNION ALL.
copy the sql from the right and left joins into a union query then add the union and the order by statements to the union query.
SELECT SpecialNumbers.Numbers, mytable.Column1, Count(mytable.Column1) AS CountOfColumn1
FROM SpecialNumbers LEFT JOIN mytable ON SpecialNumbers.Numbers = mytable.Column1
GROUP BY SpecialNumbers.Numbers, mytable.Column1
UNION
SELECT SpecialNumbers.Numbers, mytable.Column1, Count(mytable.Column1) AS CountOfColumn1
FROM SpecialNumbers RIGHT JOIN mytable ON SpecialNumbers.Numbers = mytable.Column1
GROUP BY SpecialNumbers.Numbers, mytable.Column1
ORDER BY CountOfColumn1 DESC;
Given my special numbers where 1 to 10 This turns
to
Assuming that you only wish the four missing rows added, this is not that difficult in Access, as it is easy to create a small query generating numbers from a system table:
SELECT
T.Column1,
Count(Table.[Column1]) AS [Counter]
FROM
(SELECT DISTINCT Abs([id] Mod 10) AS Column1
FROM MSysObjects
WHERE (Abs([id] Mod 10)) Between 1 And 8) As T
LEFT JOIN
[Table]
ON T.Column1 = Table.Column1
GROUP BY
T.Column1
ORDER BY
Count(Table.[Column1]) DESC,
T.Column1;
Output:

SQL return a default value if a row is not found [PostgreSQL]

I'm wondering if it was doable (in one query if possible) to make the query return a default value if a row is missing ? For example takes these 2 tables and given my query takes 2 parameter (place_id and user_id)
T1
place_id / tag_id
1 2
1 3
1 4
2 4
3 2
4 5
T2
user_id / tag_id / count
100 2 1
100 3 20
200 4 30
200 2 2
300 5 22
As you see, the pair user/tag (100,4) is missing. What I would like to archive is a query that will return me these 3 results
tag_id / count
2 1
3 20
4 0
I know that i can do this with something like this but it doesn't really match the final result as it only works if i know in advance the tag_id... and obviously only return 1 row..:
SELECT T1.tag_id, T2.count
from T1 t1
left join T2 t2 on t1.tagId=t2.tag_id
where t1.place_id=1
UNION ALL
select tag_id,0
from T1
where not exist (select 1 from T2 where user_id=100 and tag_id=4)
and tag_id=4;
EDIT: My question was not complete and had missing cases
here is an example (curtesy of #a_horse_with_no_name) http://sqlfiddle.com/#!12/67042/4
Thank you!
The outer join will already take care of what you want.
As t1 is the "left table" of the join, all rows from t1 will be returned. Columns from the "right table" (t2 in your example) will then have a null value. So you only need to convert that null to a 0:
select t1.tag_id, coalesce(t2.cnt, 0)
from T1 t1
left join T2 t2 on t1.tag_Id=t2.tag_id
and t1.place_id = 1;
SQLFiddle example: http://sqlfiddle.com/#!12/ed7bf/1
Unrelated but:
Using count as a column name is a really bad idea, because it will require you to always enclose the column name in double quotes: t2."count" because it is a reserved word. Plus it doesn't really document the purpose of the column. You should find a better name for that.

merge adjacent repeated rows into one

I want to merge adjacent repeated rows into one ,
for example , I have a table demo with two columns ,
data | order
-------------
A | 1
A | 2
B | 3
B | 4
A | 5
I want the result to be :
A
B
A
How to achieve this by one select SQL query in oracle ?
please, try something like this
select *
from table t1
where not exists(select * from table t2 where t2.order = t1.order - 1 and t1.data = t2.data)
The answer suggested by Dmitry above is working in SQL, to make it work in oracle you need to do some modifications.
order is a reserved keyword you need to escape it as follows.
select
*
from
Table1 t1
where not exists(
select * from Table1 t2
where
t2."order" = t1."order" - 1
and
t1."data" = t2."data"
) order by "order"
Working Fiddle at http://sqlfiddle.com/#!4/cc816/3
You can group by a column
Take a look at http://docs.oracle.com/javadb/10.6.1.0/ref/rrefsqlj32654.html
Example from official oracle site:
SELECT AVG (flying_time), orig_airport
FROM Flights
GROUP BY orig_airport

select distinct records where multiple rows exist for one ID based on values in another column

So I'm not exactly sure if my title is correct or misleading. It sounds simple, but I can't figure it out and haven't found a good example.
I want to select the distinct ID's from a table where the ID does not match to a certain code. For instance I have tableA as below:
tableA
ID Code
==== ====
1 AAA
1 BBB
1 CCC
2 AAA
2 DDD
2 EEE
3 BBB
3 GGG
3 HHH
The only result I would like to return is ID 3 since ID 1 and ID 2 match to code 'AAA'.
I've tried:
SELECT disctinct(ID) from tableA where code <> 'AAA'
but this returns ID 1, 2, and 3. I'm not sure if a group by would work either because I don't even want ID 1 and 2 to be returned.
Try using NOT IN:
SELECT ID
FROM TableA
WHERE ID NOT IN(SELECT ID
FROM TableA
WHERE CODE='AAA')
IN determines whether a specified value matches any value in a subquery or a list. Read more here.
Explanation:
Inner query selects all IDs which as CODE=AAA. The outer query will select all IDs which are not in the result return by inner query.
i.e., With the given data, inner query will return (1,2). Outer query will select ID which are not in (1,2) which is ofcourse 3.
This returns all rows for a given id:
select *
from tab as t1
where not exists
(select * from tab as t2
where t1.id = t2.id
and code = 'AAA')
And this just the ids without 'AAA':
select id
from tab
group by id
having count(case when code = 'AAA' then 1 end) = 0

Add Column values in sql server query

I have result of two queries like:
Result of query 1
ID Value
1 4
2 0
3 6
4 9
Result of query 2
ID Value
1 6
2 4
3 0
4 1
I want to add values column "Value" and show final result:
Result of Both queries
ID Value
1 10
2 4
3 6
4 10
plz guide me...
select id, sum(value) as value
from (
select id, value from query1
uninon all
select id, value from query2
) x
group by id
Try using a JOIN:
SELECT
T1.ID,
T1.Value + T2.Value AS Value
FROM (...query1...) AS T1
JOIN (...query2...) AS T2
ON T1.Id = T2.Id
You may also need to consider what should happen if there is an Id present in one result but not in the other. The current query will omit it from the results. You may want to investigate OUTER JOIN as an alternative.
A not particularly nice but fairly easy to comprehend way would be:
SELECT ID,SUM(Value) FROM
(
(SELECT IDColumn AS ID,ValueColumn AS Value FROM TableA) t1
OUTER JOIN
(SELECT IDColumn AS ID,ValueColumn AS Value FROM TableB) t2
) a GROUP BY a.ID
It has the benefits of
a) I don't know your actual table structure so you should be able to work out how to get the two 'SELECT's working from your original queries
b) If ID doesn't appear in either table, that's fine