Query with Left Outer Join - sql-server

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.

Related

MSSQL can't understand what's happening with the action "having count(*) lesser than <some field of other table>"

I've tried to understand some part of an exercise i'm doing and just couldn't get it.
There's a part where 'T' is selected, grouped by 'a' and than it's redirected to "having count(*) < T3.a",
and I don't know how to approach it.
I've tried googling this sort of thing and see if there are similar examples but all other examples were using regular numbers for ex.: "having count(*) < 5" and not whole fields for comparison.
The exercise is this:
MSSQL exercise
create table T(a int, b int);
insert into T values(1,2);
insert into T values(1,1);
insert into T values(2,3);
insert into T values(2,4);
insert into T values(3,4);
insert into T values(4,5);
select T3.b, (select count(T5.a)
from T T5
where T5.a = T3.b)
from (select T1.a as a, T2.b as b
from T T1, T T2
where T1.b < T2.a) as T3
where not exists (select T4.a
from T T4
group by T4.a
having count(*) < T3.a);
I thought that the having count(*) was comparing each value that was grouped by to each value of T3.a in each row and if all rows have met the criteria than the value is getting selected but I somehow get different results.
Can someone please explain to me what is really going on behind this "having count(*) < T3.a" operation?
Thank you in advance.
To repeat myself from the comments, a HAVING is like a WHERE for aggregate functions. You cannot use aggregate function in the WHERE, for example WHERE SUM(SomeColumn) > 5, so you need to do them in the HAVING: HAVING SUM(SomeColumn) > 5. This would returns any rows where the SUM of the column SomeColumn is greater than 5 in the group.
For your expression, HAVING COUNT(*) < T3.a it would only return rows where the value of COUNT(*) is less than the value of T3.a.
Let's break this down to it's separate parts.
First the FROM
from (select T1.a as a, T2.b as b
from T T1, T T2
where T1.b < T2.a) as T3
This uses the old-style deprecated cross-join syntax. It can be rewritten as a normal join:
from (select T1.a as a, T2.b as b
from T T1
join T T2 on T1.b < T2.a
) as T3
If we analyze what it does, we realize that it is actually what is known as a triangular join: every row is self-joined to every row lower than it. This was commonly done when window aggregates were not available.
WHERE
where not exists (select T4.a
from T T4
group by T4.a
having count(*) < T3.a);
This is a correlated subquery: T3.a is a reference to the outer query.
What this predicate says is: for this particular row, there must be no rows in the subquery.
The subquery itself says: take all rows in T, group them by a and count, then only include rows for which the count is less than the outer reference a.
Note that because it is an EXIST, the actual selected value is not used. I suspect this may not have been the intention.
SELECT
select T3.b, (select count(T5.a)
from T T5
where T5.a = T3.b)
We then take b from the first join, and the count from a subquery of all matching T rows. Again, this was common when window aggregates were not available.
So the whole thing can be rewritten as follows:
select T2.b, (select count(T5.a)
from T T5
where T5.a = T3.b)
from (
select *, count(*) over (partition by a) as cnt
from T
) T1
join T T2 on T1.b < T2.a
where T1.cnt < T1.a;
There is something not quite right about the logic in your query, but without knowing what the original intention was, and without seeing the table and column names, I cannot say. The triangular join in particular looks very suspect.

Do I need to handle nulls on LEFT JOINs?

There is a more senior SQL developer (the DBA) at the office who told me that in all the LEFT JOINS of my script, I must handle the scenario where the join column of the left table is possibly null, otherwise, I have to use INNER JOINs. Now, being a noob, I might be wrong here, but I can't see his point and left me needlessly confused.
His explanation was, unless the column is non-nullable, either I must
use ISNULL(LeftTable.ColumnA,<replacement value here>) on the ON clause, or
handle null values in the ON clause or the
WHERE clause, either by adding AND LeftTable.ColumnA IS NOT NULL or AND LeftTable.ColumnA IS NULL.
I thought those are unnecessary, since one uses a LEFT JOIN if one does not mind returning null rows from the right table, if the values of the right table join column does not match the left table join column, whether it be using equality or inequality. My intent is that it does not have to be equal to the right table join column values. If the left table join column is null, it is ok for me to return null rows on the right table, as a null is not equal to anything.
What is it that I am not seeing here?
MAJOR EDIT:
So I am adding table definitions and scripts. These are not the exact scripts, just to illustrate the problem. I have remove earlier edits which are incorrect as was not in front of the script before.
CREATE TABLE dbo.Contact (
ContactID int NOT NULL, --PK
FirstName varchar(10) NULL,
LastName varchar(10) NULL,
StatusID int NULL,
CONSTRAINT PK_Contact_ContactID
PRIMARY KEY CLUSTERED (ContactID)
);
GO
CREATE TABLE dbo.UserGroup (
UserGroupID int NOT NULL, --PK
UserGroup varchar(50) NULL,
StatusID int NULL,
CONSTRAINT PK_UserGroup_UserGroupID
PRIMARY KEY CLUSTERED (UserGroupID)
);
GO
CREATE TABLE dbo.UserGroupContact (
UserGroupID int NOT NULL, --PK,FK
ContactID int NOT NULL, --PK,FK
StatusID int NULL
CONSTRAINT PK_UserGroupContact_UserGroupContactID
PRIMARY KEY CLUSTERED (UserGroupID, ContactID),
CONSTRAINT FK_UserGroupContact_UserGroupId
FOREIGN KEY (UserGroupId)
REFERENCES [dbo].[UserGroup](UserGroupId),
CONSTRAINT FK_UserGroupContact_ContactId
FOREIGN KEY (ContactId)
REFERENCES [dbo].[Contact](ContactId)
);
GO
CREATE TABLE dbo.Account (
AccountID int NOT NULL, --PK
AccountName varchar(50) NULL,
AccountManagerID int NULL, --FK
Balance int NULL,
CONSTRAINT PK_Account_AccountID
PRIMARY KEY CLUSTERED (AccountID),
CONSTRAINT FK_Account_AccountManagerID
FOREIGN KEY (AccountManagerID)
REFERENCES [dbo].[Contact](ContactId),
);
GO
My original query would look like below. When I say "left table", I mean the table on the left of the ON clause in a join. If "right table", its the table on the right of the ON clause.
SELECT
a.AccountId,
a.AccountName,
a.Balance,
ug.UserGroup,
ugc.UserGroupID,
a.AccountManagerID,
c.FirstName,
c.LastName
FROM dbo.Account a
LEFT JOIN dbo.Contact c
ON a.AccountManagerID = c.ContactID
AND c.StatusID=1
LEFT JOIN dbo.UserGroupContact ugc
ON a.AccountManagerID = ugc.ContactID
AND ugc.StatusID=1
LEFT JOIN dbo.UserGroup ug
ON ugc.UserGroupID = ug.UserGroupID
AND ug.StatusID=1
WHERE
a.Balance > 0
AND ugc.UserGroupID = 10
AND a.AccountManagerID NOT IN (20,30)
Notice in the example script above, the first and second left joins has a nullable column on the left table and non-nullable column on the right table. The third left join has both nullable columns on the left and right tables.
The suggestion was to "change to inner join or handle NULL condition in where clause" or "There is use of LEFT JOIN but there are non null conditions referenced in the WHERE clause."
The suggestion is to do either of these depending on intent:
a) convert to inner join (not possible as I want unmatched rows from Account table)
SELECT
a.AccountId,
a.AccountName,
a.Balance,
ug.UserGroup,
ugc.UserGroupID,
a.AccountManagerID,
c.FirstName,
c.LastName
FROM dbo.Account a
INNER JOIN dbo.Contact c
ON a.AccountManagerID = c.ContactID
AND c.StatusID=1
INNER JOIN dbo.UserGroupContact ugc
ON a.AccountManagerID = ugc.ContactID
AND ugc.StatusID=1
INNER JOIN dbo.UserGroup ug
ON ugc.UserGroupID = ug.UserGroupID
AND ug.StatusID=1
WHERE
a.Balance > 0
AND ugc.UserGroupID = 10
AND a.AccountManagerID NOT IN (20,30)
b) handle nulls in WHERE clause (not possible as I want to return rows with nulls on column a.AccountManagerID and on ugc.UserGroupID)
SELECT
a.AccountId,
a.AccountName,
a.Balance,
ug.UserGroup,
ugc.UserGroupID,
a.AccountManagerID,
c.FirstName,
c.LastName
FROM dbo.Account a
LEFT JOIN dbo.Contact c
ON a.AccountManagerID = c.ContactID
AND c.StatusID=1
LEFT JOIN dbo.UserGroupContact ugc
ON a.AccountManagerID = ugc.ContactID
AND ugc.StatusID=1
LEFT JOIN dbo.UserGroup ug
ON ugc.UserGroupID = ug.UserGroupID
AND ug.StatusID=1
WHERE
a.Balance > 0
AND ugc.UserGroupID = 10
AND a.AccountManagerID NOT IN (20,30)
AND a.AccountManagerID IS NOT NULL
AND ugc.UserGroupID IS NOT NULL
c) handle nulls in ON clause (I settled on this which I thought doesn't make sense because it's redundant)
SELECT
a.AccountId,
a.AccountName,
a.Balance,
ug.UserGroup,
ugc.UserGroupID,
a.AccountManagerID,
c.FirstName,
c.LastName
FROM dbo.Account a
LEFT JOIN dbo.Contact c
ON a.AccountManagerID = c.ContactID
AND c.StatusID=1
AND a.AccountManagerID IS NOT NULL
LEFT JOIN dbo.UserGroupContact ugc
ON a.AccountManagerID = ugc.ContactID
AND ugc.StatusID=1
AND a.AccountManagerID IS NOT NULL
LEFT JOIN dbo.UserGroup ug
ON ugc.UserGroupID = ug.UserGroupID
AND ug.StatusID=1
AND ugc.UserGroupID IS NOT NULL
WHERE
a.Balance > 0
AND ugc.UserGroupID = 10
AND a.AccountManagerID NOT IN (20,30)
I did not provide example for ISNULL(). Also, I think he was not referring to implicit inner joins.
To recap, how do I handle this suggestion: "There is use of LEFT JOIN but there are non null conditions referenced in the WHERE clause."? He commented it's a "questionable LEFT JOIN logic".
One thing your question doesn't talk about is ANSI NULLs, whether they're on or off. If ANSI NULLs are on, comparing NULL = NULL return false, but if they're off, NULL = NULL returns true.
You can read more about ANSI NULLs here: https://learn.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql
So if ANSI NULLs are OFF, you very much care about matching a NULL foreign key to missing row in a join. Your rows with NULL foreign keys are going to match every single row where the left table was all NULLs.
If ANSI NULLs are ON, the LEFT OUTER JOIN will behave as expected, and NULL foreign keys will not match up with NULL primary keys of other missing rows.
If another dev is telling you that you need to be careful about NULLs in OUTER JOINs, that's probably a good indication that the database you're working with has ANSI NULLs OFF.
one uses a LEFT JOIN if one does not mind returning null rows from the right table
Left table LEFT JOIN right table ON condition returns INNER JOIN rows plus unmatched left table rows extended by by nulls.
One uses left join if that's what one wants.
the join column of the left table
A join is not on "the join column"--whatever that means. It is on the condition.
That might, say, be one column in the left table being equal to the same-named column in the right. Or be a function of one column in the left table being equal to the same-named column in the right. Or be a boolean function of same-named columns. Or involve/include any of those. Or be any boolean function of any of the input columns.
If the left table join column is null, it is ok for me to return null rows on the right table, as a null is not equal to anything.
It seems you are suffering from a fundamental misconception. The only thing that is "ok for me to return" is the rows you were told to return, for certain possible input.
It's not a matter of, say, coding some condition on some tables because we want certain inner join rows and then accepting whatever null-extended rows we get. If we use a left join, it's because it returns the correct inner join rows & the correct null-extended rows; otherwise we want a different expression.
It is not a matter of, say, a left table row having null meaning that that row must not be part of the inner join & must be null-extended. We have some input; we want some output. If we want the inner join of two tables on some condition no matter how that condition uses nulls or any other input values plus the unmatched left table rows then we left join those tables on that condition; otherwise we want a different expression.
(Your question uses but doesn't explain "handle". You don't tell us the rows you were told to return, for certain possible input. You don't even give us example desired output for example input or your actual output for some query. So we have no way of adddressing what your DBA's critique is trying to say about what you ought to do or what you are doing your queries.)
Going to expand a bit on my comment here; this, however, is guess work based on what we have at the moment.
based on your current wording, what you've stated is wrong. Let's take these simple tables:
USE Sandbox;
GO
CREATE TABLE Example1 (ID int NOT NULL, SomeValue varchar(10));
GO
CREATE TABLE Example2 (ID int NOT NULL, ParentID int NOT NULL, SomeOtherValue varchar(10));
GO
INSERT INTO Example1
VALUES (1,'abc'),(2,'def'),(3,'bcd'),(4,'zxy');
GO
INSERT INTO Example2
VALUES (1,1,'sadfh'),(2,1,'asdgfkhji'),(3,3,'sdfhdfsbh');
Now, let's have a simple query with a LEFT JOIN:
SELECT *
FROM Example1 E1
LEFT JOIN Example2 E2 ON E1.ID = E2.ParentID
ORDER BY E1.ID, E2.ID;
Note that 5 rows are returned. No handling of NULL was required. if you added an OR to the ON it would be non-sensical, as ParentID cannot have a value of NULL.
If, however, we add something to the WHERE for example:
SELECT *
FROM Example1 E1
LEFT JOIN Example2 E2 ON E1.ID = E2.ParentID
WHERE LEFT(E2.SomeOtherValue,1) = 's'
ORDER BY E1.ID, E2.ID;
This now turns the LEFT JOIN into an implicit INNER JOIN. The above would therefore be better written as:
SELECT *
FROM Example1 E1
JOIN Example2 E2 ON E1.ID = E2.ParentID
WHERE LEFT(E2.SomeOtherValue,1) = 's'
ORDER BY E1.ID, E2.ID;
This, however, may not be the intended output; you may well want unmatched rows (and why you intially used a LEFT JOIN. There are 2 ways you could do that. The first is add the criteria to the ON clause:
SELECT *
FROM Example1 E1
LEFT JOIN Example2 E2 ON E1.ID = E2.ParentID
AND LEFT(E2.SomeOtherValue,1) = 's'
ORDER BY E1.ID, E2.ID;
The other would be do add an OR (don't use ISNULL, it affects SARGability!):
SELECT *
FROM Example1 E1
LEFT JOIN Example2 E2 ON E1.ID = E2.ParentID
WHERE LEFT(E2.SomeOtherValue,1) = 's'
OR E2.ID IS NULL
ORDER BY E1.ID, E2.ID;
This, I imagine is what your senior is talking about.
To repeat though:
SELECT *
FROM Example1 E1
LEFT JOIN Example2 E2 ON E1.ID = E2.ParentID OR E2.ID IS NULL
ORDER BY E1.ID, E2.ID;
Makes no sense. E2.ID cannot have a value of NULL, so the clause makes no change to the query, apart from probably making it run slower.
Cleanup:
DROP TABLE Example1;
DROP TABLE Example2;
in my eyes this is very simple, as far as I understood it.
Let's try with an example.
Imagine to have 2 tables, a master and a details table.
MASTER TABLE "TheMaster"
ID NAME
1 Foo1
2 Foo2
3 Foo3
4 Foo4
5 Foo5
6 Foo6
DETAILS TABLE "TheDetails"
ID ID_FK TheDetailValue
1 1 3
2 1 5
3 3 3
4 5 2
5 5 9
6 3 6
7 1 4
TheDetails table is linked to TheMaster table through the field ID_FK.
Now, imagine to run a query where you need to sum the values of the column TheDetailValue. I would go with something like this:
SELECT TheMaster.ID, TheMaster.NAME, Sum(TheDetails.TheDetailValue) AS SumOfTheDetailValue
FROM TheMaster INNER JOIN TheDetails ON TheMaster.ID = TheDetails.ID_FK
GROUP BY TheMaster.ID, TheMaster.NAME;
You would get a list like this:
ID NAME SumOfTheDetailValue
1 Foo1 12
3 Foo3 9
5 Foo5 11
But, what is your query uses a LEFT JOIN instead of a INNER JOIN? For example:
SELECT TheMaster.ID, TheMaster.NAME, Sum(TheDetails.TheDetailValue) AS SumOfTheDetailValue
FROM TheMaster LEFT JOIN TheDetails ON TheMaster.ID = TheDetails.ID_FK
GROUP BY TheMaster.ID, TheMaster.NAME;
The result would be:
ID NAME SumOfTheDetailValue
1 Foo1 12
2 Foo2
3 Foo3 9
4 Foo4
5 Foo5 11
6 Foo6
You will obtain a NULL for each master field having no values in the details table.
How do you exclude these values? Using an ISNULL!
SELECT TheMaster.ID, TheMaster.NAME, Sum(TheDetails.TheDetailValue) AS SumOfTheDetailValue
FROM TheMaster LEFT JOIN TheDetails ON TheMaster.ID = TheDetails.ID_FK
WHERE (((TheDetails.ID_FK) Is Not Null))
GROUP BY TheMaster.ID, TheMaster.NAME;
...which would take us to these results:
ID NAME SumOfTheDetailValue
1 Foo1 12
3 Foo3 9
5 Foo5 11
...which is exactly what we obtained before using an INNER JOIN.
So, in the end, I guess your collegue is talking about the use of the ISNULL function, in order to exclude the records having no relation in another table.
That's it.
For example purpose only the query were made using MS Access (rapid test), so the ISNULL function is implemented with "Is Null", which can become "Is Not Null". In your case probably it's something like ISNULL() and/or NOT ISNULL()

Selecting Max with Lots of Other Items

Sorry for the poor title. I wasn't sure how to describe my problem. I've written a query that returns about 23,000 records. A lot of those records have similar information and I want to only select the records with the maximum of the field dbo.tblMsgsOnAir_Type8.fldBuddyLinkSigStrength. I've tried grouping by all of the other columns being selected, but it doesn't appear to work correctly. I don't fully understand SQL, especially the max and group functions. I can do simple max functions when I only want or need to select one thing. I don't understand how it works when I want to select a bunch of other data. Below is the query.
SELECT
dbo.tblmeterinfo.fldMeterSerialNumber AS "MOP_FNP_Meter",
dbo.tblMsgsOnAir_Type8.fldRBuddyId AS "MOP_FNP_FNID",
dbo.TBLMETERMAINT.fldmeterid AS "Meter_ID_Helped",
dbo.tblMsgsOnAir_Type8.fldCBuddyId AS "FNID_Helped",
dbo.fn_dt(dbo.tblMsgsOnAir_Type8.fldRBuddyToi) AS "TOI",
dbo.tblMsgsOnAir_Type8.fldBuddyLinkSigStrength AS "Sig_Str",
dbo.TBLSAWN_CIS_INFO.SML AS "Buddy_SML",
dbo.TBLMETERLIST.fldaddress AS "Buddy_Address",
dbo.TBLSAWNGISCOORD.X_COORD AS "X_Coord",
dbo.TBLSAWNGISCOORD.Y_COORD AS "Y_Coord"
FROM dbo.tblMsgsOnAir_Type8
LEFT OUTER JOIN dbo.TBLMETERLIST
ON (dbo.TBLMETERLIST.FLDREPID = dbo.tblMsgsOnAir_Type8.fldCBuddyId)
LEFT OUTER JOIN dbo.TBLMETERMAINT
ON (dbo.TBLMETERMAINT.FLDREPID = dbo.tblMsgsOnAir_Type8.fldCBuddyID)
LEFT OUTER JOIN dbo.TBLSAWN_CIS_INFO
ON (dbo.TBLSAWN_CIS_INFO.FLDREPID = dbo.tblMsgsOnAir_Type8.fldCBuddyId)
LEFT OUTER JOIN dbo.TBLSAWNGISCOORD
ON (dbo.TBLSAWNGISCOORD.SRV_MAP_LOC = dbo.TBLSAWN_CIS_INFO.SML)
LEFT OUTER JOIN dbo.tblmeterinfo
ON (dbo.tblmeterinfo.fldRepId = dbo.tblMsgsOnAir_Type8.fldRBuddyId)
WHERE dbo.tblMsgsOnAir_Type8.fldRBuddyId IN (SELECT
dbo.tblSAWN_FNPmap.Repid
FROM dbo.tblSAWN_FNPmap)
AND dbo.TBLMETERMAINT.fldmeterid IS NOT NULL
The query below is simple and does what I want, but doesn't get all of the other field. This query only returns 617 records. I would like the above query to return 617 records, but include all of the other information I've selected.
SELECT
dbo.TBLMETERMAINT.fldmeterid AS "Meter_ID_Helped",
MAX(dbo.tblMsgsOnAir_Type8.fldBuddyLinkSigStrength) AS "Max_Sig"
FROM dbo.tblMsgsOnAir_Type8
LEFT OUTER JOIN dbo.TBLMETERMAINT
ON (dbo.TBLMETERMAINT.FLDREPID = dbo.tblMsgsOnAir_Type8.fldCBuddyID)
WHERE dbo.tblMsgsOnAir_Type8.fldRBuddyId IN (SELECT
dbo.tblSAWN_FNPmap.Repid
FROM dbo.tblSAWN_FNPmap)
AND dbo.TBLMETERMAINT.fldmeterid IS NOT NULL
GROUP BY dbo.TBLMETERMAINT.fldmeterid
Probably row_number() to the rescue. You can use it to find the best records in a set, with a grouping by some subset or other. Something like
select *
from ....
where row_number over (partition by id order by fldBuddyLinkSigStrength) = 1
So SQL Server assigns a row number within the groups. Each record will be sub-grouped by id, in this case, and given 1 if it's the best strength, 2 if it's next, etc.
If you are getting duplicates have you tried using SELECT DISTINCT?
Basically how Max works is that it will select the highest value in the group.
So if you have a table:
ID | VALUE
1 | 10
1 | 7
1 | 9
2 | 6
2 | 8
And do
SELECT ID, MAX(VALUE)
FROM TABLE
GROUP BY ID
You'll get the max value per ID
ID | VALUE
1 | 10
2 | 8
If you want to get the Max while not grouping the result then you can do the group in a subselect
SELECT ID, VALUE, MAX_VALUE etc etc
FROM TABLE
JOIN ( SELECT ID, MAX(VALUE) AS MAX_VALUE FROM TABLE GROUP BY ID) as MAX ON MAX.ID = TABLE.ID
Without knowing your table structures in more detail I can't be sure this is the best way, but here's something that should work. Use the 2nd query as the left side of a left join, to pick up the extra columns:
select a.*
from (<your 2nd query>) a
left join dbo.TBLMETERLIST
on (a.FLDREPID = dbo.tblMsgsOnAir_Type8.fldCBuddyId)
left join <next table> ...
and so on. You'll also have to left join on dbo.tblMsgsOnAir_Type8 in order to pick up the columns in that table, so that's one additional left join beyond what your first query does. By the way, it's a good idea to post code here laid out so it's readable; it makes it a lot easier for others to understand.

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.

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

Resources