I am using C# and SQL Server.
Take a look at the following SQL:
SELECT table1.id, table1.description, table2.name, table2.surname
FROM table1
INNER JOIN table2 ON table1.EmpID = table2.EmpID
It is straight forward and works fine. It retrieves the data from table1 table just fine and inner joins table1.empid to table2.name and table2.surname correctly.
Now, sometimes table1.empid is null and when it is, this SQL just ignores the "row" with the null value; which is pretty normal basing on the criteria.
What I need here is to also get the "rows" with the null values and when table1.empid is null I need to set a custom value to table2.name and table2.surname.
I have been playing with isnull() but all I did is make it even worst.
Any suggestions?
Thanks
You need to do a LEFT JOIN:
SELECT table1.id, table1.description, table2.name, table2.surname FROM table1
LEFT JOIN table2 ON table1.EmpID = table2.EmpID;
Try using a UNION:
SELECT table1.id, table1.description, table2.name, table2.surname
FROM table1
INNER JOIN table2 ON table1.EmpID = table2.EmpID
UNION
SELECT table1.id, table1.description, 'Table 2 Null', 'Table 2 Null'
FROM table1
WHERE table1.empId is null
If table 1 is null and you still need the records that you cannot start with that. Start with table2 and join table1.
SELECT table1.id, table1.description, ISNULL(table1.empid, "some new value") AS name, table2.surname
FROM table2
LEFT OUTER JOIN table1 ON table2.EmpID = table1.EmpID
SELECT table1.id
,table1.description
,COALESCE(table2.name, 'DEFAULT') AS name
,COALESCE(table2.surname, 'DEFAULT') AS surname
FROM table1
LEFT JOIN table2
ON table1.EmpID = table2.EmpID
Now note, that this will also include people when the EmpID is not null but nevertheless "invalid" if they have an EmpID in table1, but it isn't found in table2, so if that's something you want to avoid, another option is this:
SELECT table1.id
,table1.description
,table2.name
,table2.surname
FROM table1
INNER JOIN table2
ON table1.EmpID = table2.EmpID
UNION ALL
SELECT table1.id
,table1.description
,'DEFAULT' AS name
,'DEFAULT' AS surname
FROM table1
WHERE table1.EmpID IS NULL
Select table1.id table1.description
, Case When table1.EmpID Is Null Then 'Some Value' Else table2.name End As Table2Name
, Case When table1.EmpID Is Null Then 'Some Value' Else table2.surname End As Table2Surname
From table1
Left Join table2
On table2.EmpID = table1.EmpID
Where table1.EmpID Is Null
Or table2.EmpID Is Not Null
Related
I want to write an SP that I will use in my c# program. I have three tables: Table1 (id pk, name, ...), Table2 (id PK, name, ...) and Table3((idT1,idT2) PK FK). So, Table3 models the n:n relationship between Table1 and Table2.
I want to retrieve all the Table2.name(s) related to a single Table1.name.
I have already tried to write a query with two inner join
CREATE PROCEDURE slct
#name nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT Table2.name from Table2
join Table3 on Table2.id = Table3.idT2 join Table1 on Table1.id = Table3.idT1 where Table1.name = '%'+#name+'%'
END
GO
Table1
|1|abc|
|2|def|
Table2
|1|xyz|
|2|mno|
Table3
|1|1|
|1|2|
|2|2|
As result, I see more records than are needed. I expected a list of Table2.name related to a single Table1.name (specified by #name parameter)
sorry for my english.
select Table2.Names from Table2
inner join
(select Table3.idT1 as SubQueryID1, Table3.idT2 as SubQueryID2
from Table3 inner join Table1 on Table1.id = Table3.idT1)
on
Table2.Id = SubQueryID2
SELECT
Table2.name
FROM Table2
INNER JOIN Table3 ON Table2.id = Table3.idT2
CROSS APPLY(
SELECT TOP 1 * FROM Table1 WHERE Table1.id = Table3.idT1
) t
WHERE
Table1.name = '%'+#name+'%'
I want to retrieve all the Table2.name(s) related to a single Table1.name.
select t2.name
from table2 t2 join
table3 t3
on t3.idT2 = t2.id
group by t2.name
having count(*) = 1;
This returns names in t2 that have only one row in table3. This makes two assumptions (both of which are reasonable for this data structure):
Names are unique in table1 and table2.
Pairs are unique in table3.
I want to retrieve all the Table2.name(s) related to a single Table1.name.
Your query actually has the right join logic. You have to clarify the scope of the where clause.
Table1.Name contains #name: you need the like operator instead of the equal operator.
Table1.Name strictly equals to #name: you have to remove the wildcards.
See below two examples:
select distinct T2.Name
from Table1 as T1
inner join Table3 as T3 on T3.IDT1 = T1.ID
inner join Table2 as T2 on T2.ID = T3.IDT2
where T1.Name like '%'+#name+'%'
or
select distinct T2.Name
from Table1 as T1
inner join Table3 as T3 on T3.IDT1 = T1.ID
inner join Table2 as T2 on T2.ID = T3.IDT2
where T1.Name = #name
As above, I would like the result to be one row of all the columns from each table where the value was met. The common field in all tables is the primary key. Any type of UNION does not work as the amount of columns is not the same in each table. I'm using an Access database so FULL OUTER JOINS are not supported. I'm using this query in an application in C#, Visual Studio and for some reason can't get do an inner join without it giving me a syntax error either. I'd ideally like to have this done in one query.
For example lets say I have the tables:
Table1
userID name age
1 Bob 24
2 John 19
Table2
userID col1 col2 col3
1 fd sd gh
...
Table3
userID col4 col5 col6 col7
1 ff hg fd et
...
And I want the result:
userID name age col1 col2 col3 col4 col5 col6 col7
1 Bob 24 fd sd gh ff hg fd et
Perhaps the closest I've got:
SELECT * FROM table1 AS b
INNER JOIN table2 AS c ON c.userID = b.userID
INNER JOIN table3 AS m ON m.userID = b.userID
WHERE userID = 1;
The error I get:
An unhandled exception of type 'System.Data.OleDb.OleDbException'
occurred in System.Data.dll
Additional information: Syntax error (missing operator) in query
expression 'c.userID = b.userID INNER JOIN table3 AS m ON
m.userID = b.UserI'.
I should add that I want the query to be adaptable (let's say I don't know the columns but I know it has userID)
Left joins should work in ms-access:
select *
from Table1 t1
left join Table2 t2
on t1.userID = t2.userID
left join Table3 t3
on t1.userID = t3.userID
This should work in Acces:
Select T1.userID, T1.name, T1.age, T2.col1, T2.col2, T2.col3, T3.col4, T3.col5, T3.col6, T3.col7 from Table1 T1
left join Table2 T2 on T2.userID=T1.userID
left join Table3 T3 on T3.userID=T1.userID
Or if you only want records present in the first table use an inner join:
Select T1.userID, T1.name, T1.age, T2.col1, T2.col2, T2.col3, T3.col4, T3.col5, T3.col6, T3.col7 from Table1 T1
inner join Table2 T2 on T2.userID=T1.userID
inner join Table3 T3 on T3.userID=T1.userID
So in the end I was close.
In MS-Access, when joining more than 2 tables you must use parentheses (around the first join?). Second of all, in my where condition I didn't specify a table for userID. See my amended query below:
SELECT * FROM table1 AS b
(INNER JOIN table2 AS c ON c.userID = b.userID)
INNER JOIN table3 AS m ON m.userID = b.userID
WHERE b.userID = 1;
Select
t1.userID
,t1.name
,tb1.age
,tb2.col1
,tb2.col2
,tb2.col3
,tb3.col4
,tb3.col5
,tb3.col6
,tb3.col7
FROM table1 tb1
INNER JOIN table2 tb2 ON tb1.userID=tb2.userID
INNER JOIN table3 tb3 ON tb1.userID=tb3.userID
WHERE --some conditions if u desire.
I think your problem in where condition.you did not specify the table.
So change.
Where userId=1
To be
Where b.userId=1
I am trying to select the most recent record. Right now it is returning all records. Which makes since, because I have not put in a filter to get most recent, I am unsure of how to do that. Here is my code:
select
c.my_Name, a.my_Num, d.myBrand, a.order_bill, a.myDate
from
[table1] a
left join
[table2] b on a.[myCode] = b.[myCode]
left join
[table3] c on c.myTag = b.myTag
left join
[table4] d on a.[myHash] = d.[myHash]
where
c.[myName] = 'test name'
I am wanting to get most recent record from the table, I am guessing the most efficient way is to get most recent a.myDate.
I'd write
SELECT TOP 1
c.my_Name, a.my_Num, d.myBrand, a.order_bill, CONVERT(char(10), a.myDate,126)
FROM [table1] a
LEFT JOIN [table2] b on a.[myCode] = b.[myCode]
LEFT JOIN [table3] c on c.myTag=b.myTag
LEFT JOIN [table4] d on a.[myHash] = d.[myHash]
WHERE c.[myName] = 'test name'
ORDER BY a.myDate DESC
Something like this might help
select c.my_Name, a.my_Num, d.myBrand, a.order_bill, MAX(a.myDate)
from [table1] a
left join [table2] b on a.[myCode] = b.[myCode]
left join [table3] c on c.myTag=b.myTag
left join [table4] d on a.[myHash] = d.[myHash]
where c.[myName] = 'test name'
group by c.my_Name, a.my_Num, d.myBrand, a.order_bill
order by a.myDate DESC
This will grab distinct records with the greatest (most recent) a.myDate, grouped by your other elements.
Be aware of duplicates. Use your duplicate criteria keys in the select statement, or whatever elements you absolutely need to be distinct.
I'm attempting to combine the logic for some of my SQL queries, and I can't seem to figure out this problem. Obviously SQL Server CE has many limitations compared to SQL Server or mySQL, but surely there's a way to solve this.
I want to do a count on one table in my database, based on some parameters, and then I want to compare this value to a value stored in a column in another table.
Let's say the database is modeled like this:
Table1:
ID int
Key string
NumberInUse int
Table2:
ID int
OtherID int
Here's the necessary parts of the query.
SELECT *
FROM Table1
LEFT JOIN Table2 ON Table1.ID = Table2.ID
WHERE Table1.Key = #key
AND (SELECT COUNT(*) FROM Table2 WHERE ID = Table1.ID AND OtherID = #otherID) < Table1.NumberInUse;
Unfortunately this query gives me this error:
There was an error parsing the query. [ Token line number = 4,Token line offset = 6,Token in error = SELECT ]`
So is there a way I can rephrase the WHERE clause of my query to utilize this comparison?
Try this:
SELECT *
FROM Table1 t1
INNER JOIN (SELECT ID
,COUNT(*) numCount
FROM Table2 t2
WHERE t2.OtherId = #otherID
GROUP BY ID) t3
ON t1.ID = t3.ID
WHERE t1.Key = #Key
AND t3.numCount < t1.NumberInUse
Sure it's not SQL. You're missing the right operand of the second LEFT JOIN:
SELECT *
FROM Table1 LEFT JOIN Table2
ON Table1.ID = Table2.ID
LEFT JOIN ????? WHUT ?????
WHERE Table1.Key = #key
AND (SELECT COUNT(*) FROM Table2 WHERE ID = Table1.ID AND OtherID = #otherID) < Table1.NumberInUse;
I have two tables (Table1 and Table2) with the same primary keys, lets say Key1 and Key2. What I need to do is seperate the records in Table1 into two groups, the duplicates (records found in Table2) and the non-duplicates. I know I could use the below, but that seems bloated and repetetive. Is there a trimmer way to do this, possibly with a single call?
SELECT Key1, Key2 FROM Table1 WHERE Key1 IN (SELECT Key1 FROM Table2) AND Key2 IN (SELECT Key2 FROM Table2);
SELECT Key1, Key2 FROM Table1 WHERE Key1 NOT IN (SELECT Key1 FROM Table2) AND Key2 NOT IN (SELECT Key2 FROM Table2);
;
This call is being made from a C# ASP.NET codebehind page.
This query does a left outer join to ensure all records from table1 are returned. It joins on Table2, and if there are no matches, than any columns in Table2 will be NULL for that row. This behavior is used in a CASE statement to set a flag telling where the Table1 row exists in Table2 or not:
select t1.*,
case when t2.Key1 is null then 'false' else 'true' end as IsDuplicate
from Table1 t1
left outer join Table2 t2 on t1.Key1 = t2.Key1
and t1.Key2 = t2.Key2
You can then filter in your application based on the IsDuplicate column.
Check the new upsert statement in SQL2008
Upsert in SQL2008