SQL Server - ISNULL not working on Update Query - sql-server

Rather than have a NULL in a column, I want a 0 to be present.
Given the following two tables:
TABLE1
ClientID OrderCount
1 NULL
2 NULL
3 NULL
4 NULL
Table2
ClientID OrderCount
1 2
3 4
4 6
NOTE: The OrderCount column in both tables is INT datatype.
UPDATE TABLE1
SET OrderCount = ISNULL(TABLE2.OrderCount,0)
FROM TABLE1
INNER JOIN TABLE2 ON TABLE2.ClientID = TABLE1.CLIENTID
When I look at table1, I see this:
ClientID OrderCount
1 2
2 NULL
3 4
4 6
So, I thought to myself - "Obviously, I should be using NULLIF and not ISNULL", so I reversed them. Same result.
What am I doing wrong here? How do I get a 0 rather than a NULL in the column?

You need a LEFT JOIN rather than an INNER JOIN. The records that don't have a matching ClientID are not even being touched by your query.

you are using INNER JOIN but you don't have client ID 2 on table2 so your result set wont include a line with 2. Replace it with LEFT JOIN

Your join is probably filtering out rows.

Related

SQL Server joining multiple CTE

I have 4 Common Table Expressions each contains 2 columns
(RowNumber, AccountNumber) but contain variable records in each CTE depending upon the query parameters. Purpose is to keep all non null account numbers at the top for each CTE after joining.
I am joining 4 CTE's using FULL Join on the basis of RowNumber. The problem I am getting is the sequence of AccountNumber is not continuous i.e. it includes some null values in between Accountnumber in some cases. I want to keep all non null values always combined and at the top with nulls. The number of AccountNumber's in each CTE are always different.
SELECT​
ISNULL(Cte_FirstYear.AccountNumber,'') as FirstYear,​
ISNULL(Cte_SecondYear.AccountNumber,'') as SecondYear,​
ISNULL(cte_ThirdYear.AccountNumber,'') as ThirdYear,​
ISNULL(cte_FourthYear.AccountNumber,'') as FourthYear​
FROM cte_ThirdYear​
FULL OUTER JOIN​
cte_FirstYear
on ​
cte_ThirdYear.RowNumber=cte_FirstYear.RowNumber​​
full outer join Cte_SecondYear​
on ​
cte_ThirdYear.RowNumber=Cte_SecondYear.RowNumber​​
full outer join cte_FourthYear​
on ​
cte_ThirdYear.RowNumber=cte_FourthYear.RowNumber​​
Here is how I am getting the output;
FirstYear SecondYear ThirdYear FourthYear
1 2 3 4
5 6 7 1
9 NULL NULL
NULL
9 9
10 NULL
Here is expected output;
FirstYear SecondYear ThirdYear FourthYear
1 2 3 4
5 6 7 1
9 9 9
10
Based on the explained by #Donnie in the link
A cross join produces a cartesian product between the two tables, returning all possible combinations of all rows. It has no on clause because you're just joining everything to everything.
A full outer join is a combination of a left outer and right outer join. It returns all rows in both tables that match the query's where clause, and in cases where the on condition can't be satisfied for those rows it puts null values in for the unpopulated fields.
You can add this line to ignore :
on cte_ThirdYear.RowNumber=cte_FirstYear.RowNumber​​ and on ​ cte_ThirdYear.RowNumber is not null and cte_FirstYear.RowNumber​​ is not null
Read this pdf : http://stevestedman.com/wp-content/uploads/TSqlJoinTypePoster1.pdf
I created another CTE which takes the maximum records from 4 ctes and generates RowNumber 1 to N (Max. Number of records in 4 CTE's) and joined all 4 CTE's with it using LEFT JOIN.
Here is how I modified the query to achieve the result;
Cte_Max(RowNumber) AS (
SELECT TOP
(
select max(c) from
(
select count(*) c from cte_FirstYear
UNION
select count(*) c from Cte_SecondYear
UNION
select count(*) c from cte_ThirdYear
UNION
select count(*) c from cte_FourthYear
) x
)
ROW_NUMBER() OVER (ORDER BY c1.id asc) as RowNumber
FROM syscolumns AS c1
CROSS JOIN syscolumns AS c2
)
select
ISNULL(cte_FirstYear.AccountNumber,'') as FirstYear,​
ISNULL(Cte_SecondYear.AccountNumber,'') as SecondYear,​
ISNULL(cte_ThirdYear.AccountNumber,'') as ThirdYear,​
ISNULL(cte_FourthYear.AccountNumber,'') as FourthYear
from Cte_Max
LEFT join cte_FirstYear
on
Cte_Max.RowNumber=cte_FirstYear.RowNumber
LEFT join
Cte_SecondYear
on
Cte_Max.RowNumber=Cte_SecondYear.RowNumber
LEFT join
cte_ThirdYear
on
Cte_Max.RowNumber =cte_ThirdYear.RowNumber
LEFT join
cte_FourthYear
on
Cte_Max.RowNumber =cte_FourthYear.RowNumber
ORDER BY Cte_Max.RowNumber

Matching two columns of two tables for a particular value in oracle

Consider there are two tables:
TABLE1 and TABLE2 ,Both of them have same attributes i.e. ID,NAME,CLASS,STATUS.
These two tables has data for all the students in the school...but managed by two independent bodies.
On the basis of unique ID I want to check that for all the students whether the data is same in both the tables.
I would be interested in retrieving the unmatched data in both tables, But don't want the unmatched data where status of a student is 'lefttheschool' in both the tables(and if status is 'lefttheschool'in one table and'present'in other ,it is unmatched and it should be retrieved).
For example:
TABLE1 ID NAME CLASS STATUS
1 A 3 PRESENT
2 B 4 LEFT
3 B 7 LEFT
TABLE2 ID NAME CLASS STATUS
1 A 3 PRESENT
2 C 4 PRESENT
3 B 5 LEFT
RESULT:ID NAME CLASS STATUS ID NAME CLASS STATUS
2 B 4 LEFT 2 C 4 PRESENT
Select all when ID is the same and other attribute is different:
select table1.*, table2.*
from table1, table2
where table1.id = table2.id
and ( table1.name <> table2.name or
table1.class <> table2.class or table1.status <> table2.status)
and (table1.status <>'LEFT' and table2.status <>'LEFT')

Rank Based on two tables

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

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 View - Combine multiple rows into 1 row

I am trying to make a new view using in MSSql 2008 from three tables:
Table 1 has customer id and transaction id
Table 1
CustomerID TransactionID
1 1
1 2
Table 2 has Purchases Transaction and Products ID
TransactionID ProductID
1 x
2 y
Table 3 has Products Names
ProductID Name
1 x
2 y
I view I would like to make should show
CustomerID Product Name
1 x, y
When I use the following query:
SELECT table1. CustomerID, table3.Name
FROM table1 LEFT OUTER JOIN
Table2 ON table2. TransactionID = table1.VisitId LEFT OUTER JOIN
Table3 ON table2. ProductID = Table3. ProductID
GROUP BY table1. CustomerID, table3.Name
I get
CustomerID Product Name
1 x
1 y
Thanks in Advance
One way to do this is to use a user defined function, something like:
SELECT table1.CustomerID, dbo.BuildStringOfCustomerProductNames(table1.CustomerID)
FROM table1
And create a user defined function like: dbo.BuildStringOfCustomerProductNames
that takes a customerid as input.
Inside there, you can run a query to loop through the table 2 and table 3 joined records to make a string, and return that.
Off hand I can't think of any other simple way to do it.

Resources