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

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

Related

How I can apply Inner Join to filter the data in Sql Server

I have table in which I inserted all the liked places records.
Like:
I have table PlaceLikes;
Id placeId likedByUserID
1 ABC 1
2 DEF 1
3 ABC 2
4 FFF 2
Result: User 1 want to get all placeID that matches with itself.
Id placeId likedByUserID
3 ABC 2
Here User 2 with ABC placeId is similar with Requestor User ID 1.
So, How I can filter the data like this
You can use exists:
select t.*
from mytable t
where
t.likedByUserID <> 1
and exists (
select 1 from mytable t1 where t1.place_id = t.place_id and t1.likedByUserID = 1
)
I think this piece of query will be able to solve your problem statement as understood by me.
DECLARE #sample_name VARCHAR (10);
SET #sample_name = 'placeId to be searched'
SELECT Id, placeId, likedByUserID FROM demo_table dt
WHERE dt.placeId = #sample_name
Do let me know if this was helpful.

SQL select entries from table where atribute equals parameter else select * entries

It is possible in SQL (ORACLE) to select all entry from a table where an atribute equals an parameter and if not select all the others entries?
like in this example:
COD | Name
1 | Monday
2 | Thursday
3 | Saturday
parameter=3
when cod equals parameter(cod=3) return entry of cod parameter(cod=3) (including cod and name)
else
return all others entries different from parameter(cod=3) (including cod and name) (like 1 Monday and 2 Thursday)
Is it possible with SQL (oracle), or i need something like PLSQL?
I'd use a correlated query and a non-correlated query:
SELECT COD, NAME
FROM TABLE a
WHERE EXISTS (SELECT 1 FROM TABLE b WHERE b.COD = a.COD AND b.COD = 3)
OR NOT EXISTS (SELECT 1 FROM TABLE c WHERE c.COD = 3)
I'm not sure if I'm following your logic, entirely, however.
And, actually, in cases where it's all from one table it can be simplified to just:
SELECT COD, NAME
FROM TABLE a
WHERE a.COD = 3
OR NOT EXISTS (SELECT 1 FROM TABLE c WHERE c.COD = 3)
IF EXISTS(SELECT 1 FROM TABLE WHERE COD=3)
THEN
SELECT COD, NAME FROM TABLE WHERE COD=3
ELSE
SELECT COD, NAME FROM TABLE
END IF

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 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