merge adjacent repeated rows into one - sql

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

Related

Apply a Substr to a distinct result in oracle

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

How to get filtered records from Sql Server 2005?

Consider that I have two tables.
One is "Table1" as shown below.
One more table is "Table2" as shown below.
Now here what I need is, I need all the records from Table1 those ID's are not in Table2's Reference column.
Please guide me how to do this.
Thanks in advance.
How to do it with your current schema (impossible to use indexes):
SELECT Table1.*
FROM Table1
WHERE NOT EXISTS
(
SELECT 1
FROM Table2
WHERE CONCAT(',', Table2.Reference, ',') LIKE CONCAT('%,', Table1.ID, ',%')
)
How this works is by completely wrapping every value in the Reference column with commas. You will end up with ,2,3, and ,7,8,9, for your sample data. Then you can safely search for ,<Table1.ID>, within that string.
How to really do it:
Normalize your database, and get rid of those ugly, useless comma-separated lists.
Fix your table2 to be:
SlNo | Reference
------+-----------
1 | 2
1 | 3
2 | 7
2 | 8
2 | 9
and add a table2Names as:
SlNo | Name
------+---------
1 | Test
2 | Test 2
Then you can simply do:
SELECT Table1.*
FROM Table1
WHERE NOT EXISTS(SELECT 1 FROM Table2 WHERE Table2.Reference = Table1.ID)

How can I select unique rows in a database over two columns?

I have found similar solutions online but none that I've been able to apply to my specific problem.
I'm trying to "unique-ify" data from one table to another. In my original table, data looks like the following:
USERIDP1 USERIDP2 QUALIFIER DATA
1 2 TRUE AB
1 2 CD
1 3 EF
1 3 GH
The user IDs are composed of two parts, USERIDP1 and USERIDP2 concatenated. I want to transfer all the rows that correspond to a user who has QUALIFIER=TRUE in ANY row they own, but ignore users who do not have a TRUE QUALIFIER in any of their rows.
To clarify, all of User 12's rows would be transferred, but not User 13's. The output would then look like:
USERIDP1 USERIDP2 QUALIFIER DATA
1 2 TRUE AB
1 2 CD
So basically, I need to find rows with distinct user ID components (involving two unique fields) that also possess a row with QUALIFIER=TRUE and copy all and only all of those users' rows.
Although this nested query will be very slow for large tables, this could do it.
SELECT DISTINCT X.USERIDP1, X.USERIDP2, X.QUALIFIER, X.DATA
FROM YOUR_TABLE_NAME AS X
WHERE EXISTS (SELECT 1 FROM YOUR_TABLE_NAME AS Y WHERE Y.USERIDP1 = X.USERIDP1
AND Y.USERIDP2 = X.USERIDP2 AND Y.QUALIFIER = TRUE)
It could be written as an inner join with itself too:
SELECT DISTINCT X.USERIDP1, X.USERIDP2, X.QUALIFIER, X.DATA
FROM YOUR_TABLE_NAME AS X
INNER JOIN YOUR_TABLE_NAME AS Y ON Y.USERIDP1 = X.USERIDP1
AND Y.USERIDP2 = X.USERIDP2 AND Y.QUALIFIER = TRUE
For a large table, create a new auxiliary table containing only USERIDP1 and USERIDP2 columns for rows that have QUALIFIER = TRUE and then join this table with your original table using inner join similar to the second option above. Remember to create appropriate indexes.
This should do the trick - if the id fields are stored as integers then you will need to convert / cast into Varchars
SELECT 1 as id1,2 as id2,'TRUE' as qualifier,'AB' as data into #sampled
UNION ALL SELECT 1,2,NULL,'CD'
UNION ALL SELECT 1,3,NULL,'EF'
UNION ALL SELECT 1,3,NULL,'GH'
;WITH data as
(
SELECT
id1
,id2
,qualifier
,data
,SUM(CASE WHEN qualifier = 'TRUE' THEN 1 ELSE 0 END)
OVER (PARTITION BY id1 + '' + id2) as num_qualifier
from #sampled
)
SELECT
id1
,id2
,qualifier
,data
from data
where num_qualifier > 0
Select *
from yourTable
INNER JOIN (Select UserIDP1, UserIDP2 FROM yourTable WHERE Qualifier=TRUE) B
ON yourTable.UserIDP1 = B.UserIDP1 and YourTable.UserIDP2 = B.UserIDP2
How about a subquery as a where clause?
SELECT *
FROM theTable t1
WHERE CAST(t1.useridp1 AS VARCHAR) + CAST(t1.useridp2 AS VARCHAR) IN
(SELECT CAST(t2.useridp1 AS VARCHAR) + CAST(t.useridp2 AS VARCHAR)
FROM theTable t2
WHERE t2.qualified
);
This is a solution in mysql, but I believe it should transfer to sql server pretty easily. Use a subquery to pick out groups of (id1, id2) combinations with at least one True 'qualifier' row; then join that to the original table on (id1, id2).
mysql> SELECT u1.*
FROM users u1
JOIN (SELECT id1,id2
FROM users
WHERE qualifier
GROUP BY id1, id2) u2
USING(id1, id2);
+------+------+-----------+------+
| id1 | id2 | qualifier | data |
+------+------+-----------+------+
| 1 | 2 | 1 | aa |
| 1 | 2 | 0 | bb |
+------+------+-----------+------+
2 rows in set (0.00 sec)

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

Help for a Sql statement

Hy at all, today is the day of ...question.
I've a single table, with a relation master-detail like this:
RecordID MasterID Field1 Field2 .... NrDetail
1 0 xxx yyyy 1
2 0 aaaa bbbb 2
3 1 hhhhh ssss 0
4 2 eee sssss 0
5 2 jjj hhhh 0
As you can see, NrDetail contain the total of "child record".
Unfortunately, i've to create this field... and i would like to write it in my table.
So my SQL question is: how to do this type of SQL to write the field NrDetail ?
Something like:
UPDATE table SET NrDetail=
(SELECT COUNT(*) as Total FROM table WHERE MasterID= RecordID)
But i think there's some mistake...
Thank you in advance !
I think that you have forgetten to specify which MasterID you want to compare with which RecordID.
How about:
UPDATE table t1 SET NrDetail=
(SELECT COUNT(*) as Total FROM table t2 WHERE t1.MasterID=t2.RecordID)
UPDATE table
SET NrDetail = (
Select Count(*)
FROM table t2
Where t2.RecordID = table.MasterID
)
In an update statement, when you want to reference the table being updated, you need to use the full reference for columns(tablename.columnname, or ideally schema.tablename.columnname). If you are using the same table in a subquery, you need to alias the table in the subquery but again use the full reference for the outer table.
ADDITION Since you mentioned that you are using MySql, you could try something like so:
Update post
Join (
Select p1.idpadre, Count(*) Total
From post p1
Group By p1.idpadre
) Z
On Z.idpadre = post.idpost
Set post.NrDetail = Z.Total