Rank Based on two tables - sql-server

I need some help to calculate the rank from two table.
Suppose i have two table - table1 and table2.
In table1, i have below info
Disease value
A 20
B 10
C 35
In table2, i have below info
Diseaselist Othervalue
A 20
B 10
D 35
E 20
I want to check here, if A from table1 is available in table 2 then it will get high rank othewise less rank. Here C in table1 has more value than A but it is not available in table2 so it will get less rank than A and B.
Kindly sugges how would i accomplish this.
Regards,
Ratan

You can join the two tables using LEFT JOIN. And to order the rows, use CASE statement.
SELECT a.Disease, a.Value
FROM Table1 a
LEFT JOIN Table2 b
ON a.Disease = b.DiseaseList
ORDER BY CASE WHEN b.DiseaseList IS NULL THEN 1 ELSE 0 END,
a.Value DESC

Related

Insert values into a table from multiple tables using sqlite query

If I have Table1 as
A B C
1 b.1 c.1
2 b.2 c.2
1 b.3 c.3
My second table Table2 as
A D E F G
1 d.1 e.1 f.1 g.1
2 d.2 e.2 f.2 g.2
I need to insert into an empty Table3 the values from above such that it looks like this.
A B C D E
1 b.1 c.1 d.1 e.1
2 b.2 c.2 d.2 e.2
1 b.3 c.3 d.1 e.1
So basically I need to insert each row of Table1 into Table3. For each row I need to check for column A and find the corresponding value D and E from the column and insert into Table3. Is it possible to do this in one single query?
To copy Table1 to Table3 I can use the query
INSERT INTO Table3(A,B,C) SELECT A,B,C FROM Table1
And then I need to take each row from Table3 and using A update the values of D and E from Table2. Is there a better solution that I can use to insert directly from both tables to Table3? Any help is appreciated, as I am a beginner with database and queries.
To merge two tables, use a join:
-- INSERT ...
SELECT A, B, C, D, E
FROM Table1
JOIN Table2 USING (A);
This will not generate a result row if no matching Table2 row is found. If you want a result row in this case (with NULLs for the missing values), use an outer join instead.
INSERT INTO Table3 (A,B,C,D,E)
SELECT t1.A, t1.B, t1.C, t2.D, t2.E FROM Table1 t1
INNER JOIN Table2 t2 ON t2.A = t1.A
This might solve your problem.

Query with Left Outer Join

I'm having trouble figuring this out.
According to Jeff Atwood A Visual Explanation of SQL Joins Left outer join produces a complete set of records from Table A, with the matching records (where available) in Table B. If there is no match, the right side will contain null.
The left table (TableA) doesn't have duplicates. The right tableB has 1 or 2 entries for each client number. The PrimaryTP designates one as primary with 1 and the other has 0.
I shouldn't have to include the line And B.PrimaryTP = 1 because TableA doesn't have duplicates. Yet if I leave it out I get duplicate client numbers. Why?
Can you help me understand how this works. It's being very confusing to me. The logic of And B.PrimaryTP = 1 escapes me. Yet it seems to work. Still, I'm scared to trust it if I don't understand it. Can you help me understand it. Or do I have a logic error hidden in the query?
SELECT A.ClientNum --returns a list with no duplicate client numbers
FROM (...<TableA>
) as A
Left Outer Join
<TableB> as B
on A.ClientNum = B.ClientNum
--eliminate mismatch of (ClientNum <> FolderNum)
Where A.ClientNum Not In
(
Select ClientNum From <TableB>
Where ClientNum Is Not Null
And ClientNum <> IsNull(FolderNum, '')
)
--eliminate case where B.PrimaryTP <> 1
And B.PrimaryTP = 1
The difference between an INNER JOIN and a LEFT JOIN is just that the LEFT JOIN still returns the rows in Table A when there are no corresponding rows in Table B.
But it's still a JOIN, which means that if there is more than one corresponding row in Table B, it will join the row from Table A to each one of them.
So if you want to make sure that you get no more than one result for each row in Table A, you have to make sure that no more than one row from Table B is found - hence the And B.PrimaryTP = 1.
If you have one client number in A and two matches in Table B, then you will get duplicates.
Suppose you have the following data,
Table-A(client Num) Table-B(client Num)
1 2
2 2
The left Join Results
Table-A(client Num) Table-B(client Num)
1 (null)
2 2
2 2
This is the cause of duplicates. So you need to take distinct values form Table B or perform Distinct on the result set.
I shouldn't have to include the line And B.PrimaryTP = 1 because TableA doesn't have duplicates. Yet if I leave it out I get duplicate client numbers. Why?
Because both rows in the right table match a row in the left table. There is no way for SQL Server to output a triangular result; it must show the columns from both tables for every joined row. And this is true for INNER JOIN as well.
DECLARE #a TABLE(a INT);
DECLARE #b TABLE(b INT);
INSERT #a VALUES(1),(2);
INSERT #b VALUES(1),(1);
SELECT a.a, b.b FROM #a AS a
LEFT OUTER JOIN #b AS b ON a.a = b.b;
SELECT a.a, b.b FROM #a AS a
INNER JOIN #b AS b ON a.a = b.b;
Results:
a b
-- ----
1 1
1 1
2 NULL
a b
-- --
1 1
1 1
On the link that you gave the joins are explained very good. So the problem is that you have several records from table A (no matter that there are no duplicates) is that to 1 record in A there are 2 records in B (in some cases). To avoid this you can use either DISTINCT clause, either GROUP BY clause.
The LEFT OUTER JOIN will give you all the records from A with all the matching records from B. The difference with an INNER JOIN is that if there are no matching records in B, an INNER join will omit the record from A entirely, while the LEFT join will then still include a row with the results from A.
In your case, however, you may also want to check out the DISTINCT keyword.

Left outer join funny results [duplicate]

This question already has answers here:
Why and when a LEFT JOIN with condition in WHERE clause is not equivalent to the same LEFT JOIN in ON? [duplicate]
(5 answers)
Closed 9 years ago.
please take a look at below 2 queries regarding left outer join and tell me why there are differences.
Query 1 returns 1489 rows:
SELECT distinct a.GMS_MATERIALNUMBER,a.MATERIAL_DESCRIPTION, b.LDMC
FROM [AP_GDC2_PREPARATION_TEST].[dbo].[GDM_AUTOPULL] a
left outer join [AP_GDC2_STAGING_TEST].[dbo].[CFS_DIS_LDMC] b on
a.GMS_MATERIALNUMBER = b. GMS_MATERIALNUMBER and b.SAP_COMPANY_CODE= '1715'
and a.CFS_ORGANIZATION_CODE like 'rd_kr'
Query 2 returns only 295 rows which gives the same number of rows as when i do a simple select * from a where CFS_ORGANIZATION_CODE like 'rd_kr'
SELECT distinct a.GMS_MATERIALNUMBER,a.MATERIAL_DESCRIPTION, b.LDMC
FROM [AP_GDC2_PREPARATION_TEST].[dbo].[GDM_AUTOPULL] a
left outer join [AP_GDC2_STAGING_TEST].[dbo].[CFS_DIS_LDMC] b on
a.GMS_MATERIALNUMBER = b. GMS_MATERIALNUMBER and b.SAP_COMPANY_CODE= '1715'
where a.CFS_ORGANIZATION_CODE like 'rd_kr'
Basically query 2 is the result i wanted, but my question is why query 1 does not work? how exactly does the SQL server work in the background when it comes to the ON clause in the left outer join ?
Cheers
Both are literally different.
The first query does the filtering of table before the joining of tables will take place.
The second one filters from the total result after the joining the tables is done.
Here's an example
Table1
ID Name
1 Stack
2 Over
3 Flow
Table2
T1_ID Score
1 10
2 20
3 30
In your first query, it looks like this,
SELECT a.*, b.Score
FROM Table1 a
LEFT JOIN Table2 b
ON a.ID = b.T1_ID AND
b.Score >= 20
What it does is before joining the tables, the records of table2 are filtered first by the score. So the only records that will be joined on table1 are
T1_ID Score
2 20
3 30
SQLFiddle Demo
because the Score of T1_ID is only 10. The result of the query is
ID Name Score
1 Stack NULL
2 Over 20
3 Flow 30
SQLFiddle Demo
While the second query is different.
SELECT a.*, b.Score
FROM Table1 a
LEFT JOIN Table2 b
ON a.ID = b.T1_ID
WHERE b.Score >= 20
It joins the records first whether it has a matching record on the other table or not. So the result will be
ID Name Score
1 Stack 10
2 Over 20
3 Flow 30
SQLFiddle Demo
and the filtering takes place b.Score >= 20. So the final result will be
ID Name Score
2 Over 20
3 Flow 30
SQLFiddle Demo
The difference is because you made an LEFT JOIN.
So you get all rows from your first table and all that match from your second table.
In the second query you JOIN first, and after you set your WHERE statement to reduce the result.

Sql Server,use a subquery to find value in one table that is not in another

I am comparing an original table in SQL server to an Update table. I'm trying to find how many "First Numbers" have changed. As they do change in this system. But, this query seems to bring back "First Numbers" that that are equal to both tables. What am I doing wrong?
select *
from
tblBlue
where
Exists (Select 'x'
From tblRed
Where tblRed.FirstNumber != tblBlue.FirstNumber
and tblRed.ID = tblBlue.ID)
Example data:
tblRed
ID FirstNumber
1 10
2 20
3 30
4 40
tblBlue
1 5
2 20
3 35
4 40
I would expect to see:
1 5
3 35
Your query should work (see example at SQL Fiddle.) Could you post example data for which it's returning the wrong results?
A slightly clearer way to write it:
select *
from tblBlue new
join tblRed old
on new.ID = red.ID
where new.FirstNumber <> old.FirstNumber
Easier solution: use a left join
SELECT r.*
FROM tblRed r
LEFT JOIN tblBlue b ON b.ID = r.ID AND b.FirstNumber = r.FirstNumber
WHERE b.ID IS NULL
This will return records in tblRed that satisfy one of two conditions: 1) the ID isn't even found in tblBlue, i.e. a new record. or 2) the IDs were found, but the numbers have changed. Because if both the ID is the same and the FirsTNumber is the same, then b.ID will not be NULL, thus a match, and you can exclude it from the resultset of different values.

Get union of two table and taking data with a condition

I have two tables
table-a
id name
100 asd
101 ass
102 gdd
103 hgf
104 cvd
105 erf
table-b
id filter
100 red
101 blue
100 green
100 yellow
102 black
102 red
103 dark
Table-a is the master table and that have all the id's.but Table two is the one which has 'filter' data.
from these two table I want to find out all those 'id's which does not have minimum 2 filters.
note that table-b does not have all the itemnumbers in table-a, and i want all that itemnumber irrespective of if that is in table-a or table-b.I have tried inner joining these two tables and getting data out but nothing worked.
Select A.ID, A.Name, count(*)
from tableA A
LEFT JOIN tableB B on A.ID = B.ID
Group By A.ID, A.name
having count(*) <= 1
LEFT JOIN gives all records from A and only those in B which match.
The group by ID and name let us count the number of filters found in
each
The having says give me any items with a count less than or
equal to 1. (or less than the minimum 2)
Thus results would be.
101 ass 1
103 hgf 1
104 cvd 0
105 erf 0
select
*
from
table-a a
left join (
select id, count(id) as c from table-b group by id
) v on a.id = v.id
where isnull(v.id, 0) < 2
I think this would work in SQL Server (tested in SQLite and usually the two are fairly compatible when it comes to inline view syntax). But syntax issues aside, inline views can make working with sets easier to visualize.
select TA.id, name
from TA
inner join
(
select id from TA
where not exists (select id from TB where TA.id = TB.id)
UNION
select id from TB
group by id having count(filter) < 2
) as FOO
on TA.id = FOO.id
The default behavior of UNION is to remove duplicates.
The first UNIONed set consists of the ids from table A that have no filter (no counterpart in the filters table B).
The second UNIONed set consists of the ids from the filters table, table B, that have only 1 filter.
We inner join those unioned sets back to Table A to get the entity Name.

Resources