SQL display data which is not mapped in another table - sql

I am looking for a query to a result where I can see only userid1 data whose provider is not mapped in Table 2; Here is my table definition and data;
Table 1
userid providerid
1 101
1 104
1 106
1 107
2 102
2 103
2 104
Table 2
providerid
101
102
103
104
105
106
107
108
109
110
query required as per the o/p:-
userid providernotavailable
1 102
1 103
1 105
1 108
1 109
1 110
2 101
2 105
2 106
2 107
2 108
2 109
2 110

You can use the not in operator:
SELECT *
FROM table1
WHERE providerid NOT IN (SELECT providerid FROM table2)

Multiple versions: fist with NOT IN
SELECT table1.*
FROM table1
WHERE table1.providerId NOT IN ( SELECT table2.providerId FROM table2 )
Second with NOT EXISTS:
SELECT table1.*
FROM table1
WHERE NOT EXISTS ( SELECT 1
FROM table2
WHERE table1.providerId = table2.providerId )
This next one is a bit strange: we do a LEFT JOIN and we check that the second table hasn't matched:
SELECT table1.*
FROM table1
LEFT JOIN table2
ON table1.providerId = table2.providerId
WHERE table2.providerId IS NULL
Which of the three versions above performs better depends (mostly) on the cardinality of the two tables.

Sorry, I misunderstood the question. This should do the trick.
The first part of the query selects all the pairs userId - providerId. The second part removes all the ones present in table1.
SELECT U.userId, P.providerId
FROM (SELECT DISTINCT table1.userId FROM table1) U, table2 P
MINUS
SELECT table1.* FROM table1

EDIT
this is the table structure i have used to get the output
SQL> desc tab1
Name Null? Type
---------------------------- -------- ----------------
USERID NUMBER(38)
PROVIDERID NUMBER(38)
SQL> desc tab2
Name Null? Type
---------------------------- -------- ----------------
PROVIDERID NUMBER(38)
SQL> select distinct(a.userid),b.providerId from tab1 a, tab2 b
minus
select * from tab1 ;
USERID PROVIDERID
---------- ----------
1 102
1 103
1 105
1 108
1 109
1 110
2 101
2 105
2 106
2 107
2 108
2 109
2 110
13 rows selected.

SELECT a.userid, b.providerid FROM table1 a, table2 b
WHERE a.providerid IS NOT NULL
MINUS
SELECT userid, providerid FROM table1 a
WHERE a.providerid IS NOT NULL;
The query bring the desired output...
Thanks all for ur efforts.

Related

SQL Server : multiple rows single line

I would like to get the representation of one record based on the primary key value from multiple tables. As shown below, each table can have multiple values based on this primary key value.
TABLE-1
ID
NAME
1
AA
2
BB
3
CC
4
DD
5
EE
TABLE-2
ID
SCHOOL
AUT
1
11
A
2
11
A
2
12
B
3
11
A
4
12
A
4
13
B
5
13
A
TABLE-3
ID
TC
1
101
2
102
2
103
2
104
3
105
4
106
4
107
5
108
The result below is the value obtained with an OUTER JOIN.
SELECT
T1.ID, T2.SCHOOL, T3.TC, T2.AUT
FROM
T1
LEFT OUTER JOIN
T2 ON T1.ID = T2.ID
LEFT OUTER JOIN
T3 ON T1.ID = T3.ID
ORDER BY
T1.ID ASC
ID
SCHOOL
TC
AUT
1
11
101
A
2
11
102
A
2
12
102
B
2
11
103
A
2
12
103
B
2
11
104
A
2
12
104
B
3
11
105
A
4
12
106
A
4
13
106
B
4
12
107
A
4
13
107
B
5
13
106
A
How can I get the result like below?
ID
SCHOOL
TC1
TC2
TC3
1
11
101
2
11
102
103
104
3
11
105
4
12
106
107
5
13
108
The important thing here is that in the result value, SCHOOL only shows that AUT is 'A'.
I would appreciate it if you let me know your query.
It looks, from your desired results, you just need to use row_number in combination with a conditional aggregate. Your sample data seems a little inadequate, I can't see any requirement for table1 at all.
Try the following:
with t as (
select t2.id,t2.school,t3.tc, Row_Number() over(partition by t2.id order by t3.tc) col
from t2 join t3 on t2.id=t3.id
where aut='A'
)
select id,school,
max(case when col=1 then tc end) TC1,
max(case when col=2 then tc end) TC2,
max(case when col=3 then tc end) TC3
from t
group by id, school
Example SQL Fiddle
SELECT
T1.ID, T2.SCHOOL,
GROUP_CONCAT(T3.TC),
GROUP_CONCAT(T2.AUT)
FROM
T1
LEFT OUTER JOIN
T2 ON T1.ID = T2.ID
LEFT OUTER JOIN
T3 ON T1.ID = T3.ID
GROUP BY
T1.ID, T2.SCHOOL
WHERE
T2.AUT = ‘A’
ORDER BY
T1.ID ASC
Notice that GROUP_CONCAT concatenates the values in the row.
EDIT: oh my, haven't seen that it's a SQL Server question!
Just replace GROUP_CONCAT with STRING_AGG if you’re using SQL Server 2017 or newer.

Find rows with no match

I need to compare and identify all IDs that have a mismatch in the codes between the categories, upper and lower case are only examples and I cannot base the join on the category field as they are different.
e.g: ID 1 - cat A, a have the same code but ID 3, cat E and e have a mismatch, same with ID#4.
Edit: sorry - after posting the question, and looking at the answers I have realized that my question was not conveying what I am looking for, and I have mocked up data incorrectly. The Category doesn't always have the same name as uppercase/lowercase letters, this was only meant to be an example.
T1
ID Cat Code
1 A 100
1 a 100
1 B 101
1 b 101
2 C 102
2 D 103
2 d 103
3 E 104
3 e 107
3 F 105
3 g 106
4 I 109
4 i 110
5 ABC 111
5 XYZ 112
5 KLM 123
6 PQR 113
6 STU 113
Desired output:
ID Cat Code
3 E 104
3 e 107
4 I 109
4 i 110
5 ABC 111
5 XYZ 112
5 KLM 123
This answers the original version of the question.
Use exists:
select t1.*
from t1
where exists (select 1
from t1 tt1
where tt1.id = t1.id and
upper(tt1.cat) = upper(t1.cat) and
tt1.cat <> t1.cat and
tt1.code <> t1.code
);
Oracle is case-sensitive by default.
You can use a self join like below to handle this issue:
select t1.*
from tablename t1
inner join tablename t2 on t2.ID = t1.ID and upper(t1.Cat) = upper(t2.Cat)
where t1.Code <> t2.Code

Query for 1 to many table

So I have a situation which can be referred to the table below:
TABLE A TABLE B TABLE C
ID TOTAL_PRICE ORDER_ID ID ID ORDER ID
1 10 101 101 1001 101
2 20 101 103 1002 101
3 25 103 1003 103
4 10 103 1004 103
With all these tables I'm expecting of this result:
EXPECTED OUTPUT
ID TOTAL_PRICE ORDER_ID ID
1 10 101 1001
2 20 101 1002
3 25 103 1003
4 10 103 1004
And the result that I get follows:
REAL OUTPUT
ID TOTAL_PRICE ORDER_ID ID
1 10 101 1001
1 10 101 1002
2 20 101 1001
2 20 101 1002
3 25 103 1003
3 25 103 1004
4 10 103 1003
4 10 103 1004
My sql as follows and I'm using SQL Oracle:
SELECT a.id, a.total_price, a.order.id, c.id
FROM a,b,c
WHERE a.order_id=b.id AND b.id=c.order_id
With that situation, how can I solve the problem in order to get the expected output? Thank you.
It seems that you want to assign one id from table c for each row from table a given your matching tables criteria. For this you could use row_number to enumerate your rows inside tables a and c and then assign this information with the row number respectively:
select
a.id, a.total_price, a.order_id, c.id
from (select *, row_number over (partition by order_id order by id) as rn from a) a
join b on a.order_id = b.id
join (select id, order_id, row_number over (partition by order_id order by id) as rn from c) on b.id = c.order_id
where a.rn = c.rn

How to write query to find duplicate combination of values in jumbled order in SQL Server table

I am having table values like as follow:
ID Column1
101 a
101 b
101 c
102 aa
102 bb
102 cc
103 b
103 a
103 c
104 cc
104 aa
104 bb
105 c
105 a
105 b
How to write SQL query to display result as shown below
ID column1
101 a
101 b
101 c
102 aa
102 bb
102 cc
If you group by column1 it will eliminate any duplicates for that. But then to display ID you will needs some sort of aggregate function such as MIN or MAX to show that, otherwise you will get an error.
SELECT MIN(ID) as ID, column1
GROUP BY column1
ORDER BY column1
Should result in
ID column1
101 a
101 b
101 c
102 aa
102 bb
102 cc
There is more than one way to to do this but as the question is a bit ambiguous it is difficult to determine exact requirements from this but here's a couple of options:
Order by the smallest id then by column1 alphabetically
SELECT MIN(ID) as ID, column1
GROUP BY column1
ORDER BY MIN (ID), column1
Order by length of column1 and then column1 alphabetically
SELECT MIN(ID) as ID, column1
GROUP BY column1
ORDER BY LEN (column1), column1

SQL Server: Include Missing data in Query

I have two tables in SQL Server that looks as follows,
Table 1:
Store Type
100 A
101 B
102 B
103 B
104 C
105 C
106 A
107 A
108 D
109 D
110 C
111 B
112 D
and table 2:
Store Units
100 5
101 3
102 10
103 6
104 6
105 8
I want to combine the two tables in a query with a relationship link between the Store column of the two tables. The problem i have is that if i create a query between the two then the stores from 106 to 112 does not appear in the table. The query looks as follows,
SELECT dbo.Table1.Store,
dbo.Table1.Type,
dbo.Table2.Units
FROM Table1 INNER JOIN Table2
ON dbo.Table1.Store=dbo.Table2.Store
What should i do to include the stores that does not appear in Table2 (106-112) but in Table1 and make there Units = 0, such that the query table look as follows,
Store Type Units
100 A 5
101 B 3
102 B 10
103 B 6
104 C 6
105 C 8
106 A 0
107 A 0
108 D 0
109 D 0
110 C 0
111 B 0
112 D 0
You want a left outer join instead of an inner join:
SELECT t1.Store, t1.Type, COALESCE(t1.Units, 0) as Units
FROM Table1 t1 LEFT JOIN
Table2 t2
ON t1.Store = t2.Store;
I also introduced table aliases for your query to make it more readable. Note the use of coalesce() so you get 0 for Units instead of NULL.
SELECT dbo.Table1.Store, dbo.Table1.Type, coalesce(dbo.Table2.Units, 0) As Units
FROM Table1
LEFT JOIN Table2 ON dbo.Table1.Store=dbo.Table2.Store