My query on SQL Server:
select
s.learners_id, s.cv_student_id,
s.first_name + ' ' + s.last_name student_name,
p.program_name, dc.fulldate program_start_date,
sd.discount_value, dt.type_name
from
fact_student_programs_t sp
left join
object_sTATUSES_T os on os.object_statusid = sp.status_id
inner join
dim_programs_t p on p.programs_sk_id = sp.programs_sk_id
left join
dim_calendar dc on dc.datekey = sp.start_date_key
inner join
dim_students_t s on s.students_sk_id = sp.students_sk_id
outer join
(select
s.learners_id, sd.discount_value, dt.type_name
from
fact_student_discountS_T sd
inner join
discount_types_t dt on dt.id = sd.discount_type_id
inner join
dim_students_t s on s.students_sk_id = sd.students_sk_id
where
sd.curr_in = 1) discounts on discounts.learners_id = s.learners_id
where
sp.curr_in = 1
and dc.fulldate is not null
and os.status_name in ('Active')
and s.learners_id in ('201328', '237744', '237817', '239826', '308486', '308961',
'308973', '309352', '311521', '312269', '312951',
'313254', '313289', '384170', '384224', '384228',
'408911', '408912', '408936', '411293', '411308',
'411322', '411324', '411325', '411352', '411413',
'411417', '412865', '412923')
I am trying to join these two queries and am having trouble. Is the outer join statement in the wrong place? Can someone please help me fix this code?
EDIT:
outer join is not valid syntax here, so I am using left join. The query still returns an error:
Msg 4104, Level 16, State 1. The multi-part identifier "dt.type_name" could not be bound. Msg 4104, Level 16, State 1. The multi-part identifier "sd.discount_value" could not be bound. (Line 2)
Summary
outer join is not valid in SQL Server/t-sql I believe. It should either be left outer join, right outer join or full outer join.
In your situation, I suspect you want it to be a left outer join.
Explanation/longer version
In left and right outer joins, the 'left' and 'right' refer to the tables/etc literally to the left and right on the join (e.g., before and after the join, respectively).
In a left outer join, it takes all the values from the table on the left (first table) and any matching rows in the table on the right
In a right outer join, it takes all the values from the table on the right (second table) and any matching rows in the table on the left
A full outer join gets all rows from both tables, and matches them when they can.
Here is an example
/* Data setup */
CREATE TABLE #T1 (T1_ID int);
CREATE TABLE #T2 (T2_ID int);
INSERT INTO #T1 (T1_ID) VALUES (1), (2);
INSERT INTO #T2 (T2_ID) VALUES (1), (3);
/* Example joins */
SELECT #T1.T1_ID, #T2.T2_ID
FROM #T1
LEFT OUTER JOIN #T2 ON #T1.T1_ID = #T2.T2_ID;
SELECT #T1.T1_ID, #T2.T2_ID
FROM #T1
RIGHT OUTER JOIN #T2 ON #T1.T1_ID = #T2.T2_ID;
SELECT #T1.T1_ID, #T2.T2_ID
FROM #T1
FULL OUTER JOIN #T2 ON #T1.T1_ID = #T2.T2_ID;
/* Results
-- LEFT OUTER JOIN
T1_ID T2_ID
1 1
2 NULL
-- RIGHT OUTER JOIN
T1_ID T2_ID
1 1
NULL 3
-- FULL OUTER JOIN
T1_ID T2_ID
1 1
2 NULL
NULL 3
*/
Given you have WHERE s.learners_id in (...) in your WHERE clause, it implies you do not want rows where s.learners would be NULL.
If you had a right outer join, that WHERE requirement will effectively turn the right outer join into an inner join (as it would exclude all rows where s.learners_id is NULL).
If you had a full outer join, that WHERE requirement would effectively turn the full outer join into a left outer join - along similar logic lines.
Related
I'm trying to run this SQL Expression in Access:
Select *
From ((TableA
Left Join TableB
On TableB.FK = TableA.PK)
Left Join TableC
On TableC.FK = TableB.PK)
Left Join (SELECT a,b,c FROM TableD WHERE b > 1) AS TableD
On (TableD.FK = TableC.PK AND TableA.a = TableD.a)
but it keeps getting error: Join-Expression not supported.
Whats the problem?
Sorry, im just starting with Jet-SQL and in T-SQL its all fine.
Thanks
The issue is that the final outer join condition TableA.a = TableD.a will cause the query to contain ambiguous outer joins, since the records to which TableA is joined to TableD will depend upon the results of the joins between TableA->TableB, TableB->TableC and TableC->TableD.
To avoid this, you'll likely need to structure your query with the joins between tables TableA, TableB & TableC existing within a subquery, the result of which is then outer joined to TableD. This unambiguously defines the order in which the joins are evaluated.
For example:
select * from
(
select TableA.a, TableC.PK from
(
TableA left join TableB on TableA.PK = TableB.FK
)
left join TableC on TableB.PK = TableC.FK
) q1
left join
(
select TableD.a, TableD.b, TableD.c, TableD.FK from TableD
where TableD.b > 1
) q2
on q1.a = q2.a and q1.PK = q2.FK
Consider relating every join to the FROM table to avoid having to nest relations.
SELECT *
FROM ((TableA
LEFT JOIN TableB
ON TableB.FK = TableA.PK)
LEFT JOIN TableC
ON TableC.FK = TableA.PK)
LEFT JOIN
(SELECT FK,a,b,c
FROM TableD WHERE b > 1
) AS TableD
ON (TableD.FK = TableA.PK)
AND (TableD.a = TableA.a)
i am new to SQL and have been trying to have an SQL query in MS Access to join multiple tables using the below sql. This is for doing access testing.
Have explained what i intent to achieve in bold
SELECT
Table1.Role,
Table1.Object,
Table 1 is the base table which has role, authorization object
Table2.Role,
Table2.User_Name,
Table 2 has the users mapped to the role
Table3.Org_Level_Desp,
Table3.Org_LEvel_Values_1,
Table 3 has controls at organization level, this determine which company or plant the user can access
Table4.Role_Description,
Table 4 has role descriptions for roles mentioned in Table 1
Table5.Full_Name,
Table5.Department,
Table 5 has user name and department. Common field is user name from table 2
FROM
Table1
RIGHT JOIN Table2 ON Table1.Role=Table2.Role
RIGHT JOIN Table3 ON Table1.Role=Table3.Role
RIGHT JOIN Table4 ON Table1.Role=Table4.rOLE
Joining required tabled from Table 2, 3 and 4 to Table 1
FROM
Table2
RIGHT JOIN Table5 ON Table2.USER_NAME=Table5.USer
Joining required tables from table 5 to table 1
I am getting multiple syntax error for the above query. I think i am missing on something basic - Can anyone help ?
Thanks !
Uday
Seems i cannot add more in comment. Sorry, below is the code that i updated, still getting the same error. Can you please advise ?
SELECT
TABLE1.Role,
TABLE1.Object,
TABLE1.Field_name,
TABLE1.Value,
TABLE1.[and],
TABLE1.ID_whether_object_is_deleted,
TABLE2.Role,
TABLE2.User_Name,
TABLE2.End_date,
TABLE3.Org_Level_Control,
TABLE3.Org_LEvel_Values_1,
TABLE3.Org_LEvel_Values_2,
Table4.Role_Description,
TABLE6.Field_Short_Description,
TABLE7.Object_Level_Desp,
TABLE8.Auth_Obj_Text,
TABLE5.Full_Name,
TABLE5.Department,
TABLE9.Valid_to,
TABLE9.Lock,
from ((((((TABLE1 INNER JOIN TABLE2 ON TABLE1.Role=TABLE2.Role)
INNER JOIN TABLE3 ON TABLE1.Role=TABLE3.Role)
INNER JOIN Table4 ON TABLE1.Role=Table4.role)
INNER JOIN TABLE6 ON TABLE1.Field_Name=TABLE6.Field_Name)
INNER JOIN TABLE7 ON TABLE1.[Object]=TABLE7.Org_Object)
INNER JOIN TABLE8 ON AGR_TABLE1.Field_name=TABLE8.Field_Name)
FROM
(TABLE2 INNER JOIN TABLE5 ON TABLE2.USER_NAME=TABLE5.[USer])
INNER JOIN TABLE9 ON TABLE2.USER_NAME=TABLE9.[User]);
Below is the code that i updated, still getting the same error. Can you please advise ?
SELECT
TABLE1.Role,
TABLE1.Object,
TABLE1.Field_name,
TABLE1.Value,
TABLE1.[and],
TABLE1.ID_whether_object_is_deleted,
TABLE2.Role,
TABLE2.User_Name,
TABLE2.End_date,
TABLE3.Org_Level_Control,
TABLE3.Org_LEvel_Values_1,
TABLE3.Org_LEvel_Values_2,
Table4.Role_Description,
TABLE6.Field_Short_Description,
TABLE7.Object_Level_Desp,
TABLE8.Auth_Obj_Text,
TABLE5.Full_Name,
TABLE5.Department,
TABLE9.Valid_to,
TABLE9.Lock,
from ((((((TABLE1 INNER JOIN TABLE2 ON TABLE1.Role=TABLE2.Role)
INNER JOIN TABLE3 ON TABLE1.Role=TABLE3.Role)
INNER JOIN Table4 ON TABLE1.Role=Table4.role)
INNER JOIN TABLE6 ON TABLE1.Field_Name=TABLE6.Field_Name)
INNER JOIN TABLE7 ON TABLE1.[Object]=TABLE7.Org_Object)
INNER JOIN TABLE8 ON AGR_TABLE1.Field_name=TABLE8.Field_Name)
I have no idea why you would want RIGHT JOIN, particularly if you are learning SQL. Start with INNER JOIN. If that is leaving out rows, then move to LEFT JOIN.
The syntax in MS Access uses parentheses:
SELECT . . .
FROM (((Table1 INNER JOIN
Table2
ON Table1.Role = Table2.Role
) INNER JOIN
Table3
ON Table1.Role = Table3.Role
) INNER JOIN
Table4
ON Table1.Role = Table4.rOLE
) INNER JOIN
Table5
ON Table2.USER_NAME = Table5.USer
You can then select the columns you want in the SELECT.
Note that the parentheses would look quite awkward in any other database.
Re: your updated SQL.
Value is a reserved word in Access SQL, so may be others like Role, Object, Lock. Put these into [square brackets], both in the SELECT and the FROM clause.
And you have an extraneous comma at the end of your SELECT clause:
TABLE9.Valid_to,
TABLE9.Lock, <== delete this comma
from ((((((TABLE1 INNER JOIN TABLE2 ON TABLE1.Role=TABLE2.Role)
I have a query in sqlserver that needs to be translated to sqlite3, but this query uses "Right outer join", the problem is that sqlite doesn't support this operator yet.
how can I translate this query to use only "left outer join" instead of "right" outer join?
SELECT *
FROM P RIGHT OUTER JOIN
CL RIGHT OUTER JOIN
C LEFT OUTER JOIN
CC ON C.IDC = CC.RIDC ON
C.IDC = C.RIDCL ON P.IDP = C.RIDP
Thanks.
PS: I'm having trouble also with the sqlite joins precedence and associativity, don't know how it may alter the final result by reordering the tables.
In this query, the table c is in the middle. So that is driving the query.
Your on conditions are in strange places. I am guessing this is what you mean:
SELECT *
FROM C LEFT OUTER JOIN
CC
ON C.IDC = CC.RIDC LEFT OUTER JOIN
P
ON P.IDP = C.RIDP LEFT OUTER JOIN
CL
ON CL.IDC = C.RIDCL
An additional remark on the join syntax.
Most people write
Tab1 JOIN Tab2 ON ... JOIN Tab3 ON ... JOIN Tab4 ON ...
probably because this is the "natural" way, one table after the other.
But your joins use the "other" syntax i usually try to avoid.
Tab1 JOIN Tab2 JOIN Tab3 JOIN Tab4 ON ... ON ... ON ...
Logically joins are processed in the order of ON, so adding parens results in:
( P
RIGHT OUTER JOIN
( CL
RIGHT OUTER JOIN
( C
LEFT OUTER JOIN
CC
ON C.IDC = CC.RIDC
) p
ON C.IDC = C.RIDCL
)
ON P.IDP = C.RIDP
)
Rewriting it results in a join order C-CC-CL-P. This is not the C-CC-P-CL order Gordon used, but in your case this doesn't matter, because C is the main table :-)
I have the following sql statement:
select
a.desc
,sum(bdd.amount)
from t_main c
left outer join t_direct bds on (bds.repid=c.id)
left outer join tm_defination def a on (a.id =bds.sId)
where c.repId=1000000134
group by a.desc;
When I run it I get the following result:
desc amount
NW 12.00
SW 10
When I try to add another left outer join to get another set of values:
select
a.desc
,sum(bdd.amount)
,sum(i.amt)
from t_main c
left outer join t_direct bds on (bds.repid=c.id)
left outer join tm_defination def a on (a.id =bdd.sId)
left outer join t_ind i on (i.id=c.id)
where c.repId=1000000134
group by a.desc;
It basically doubles the amount field like:
desc amount amt
NW 24.00 234.00
SE 20.00 234.00
While result should be:
desc amount amt
NW 12.00 234.00
SE 10.00 NULL
How do I fix this?
If you really need to receive the data as you mentioned, your can use sub-queries to perform the needed calculations. In this case you code may looks like the following:
select x.[desc], x.amount, y.amt
from
(
select
c.[desc]
, sum (bdd.amount) as amount
, c.id
from t_main c
left outer join t_direct bds on (bds.repid=c.id)
left outer join tm_defination_def bdd on (bdd.id = bds.sId)
where c.repId=1000000134
group by c.id, c.[desc]
) x
left join
(
select t.id, sum (t.amt) as amt
from t_ind t
inner join t_main c
on t.id = c.id
where c.repID = 1000000134
group by t.id
) y
on x.id = y.id
In the first sub-select you will receive the aggregated data for the two first columns: desc and amount, grouped as you need.
The second select will return the needed amt value for each id of the first set.
Left join between those results will gives the needed result. The addition of the t_main table to the second select was done because of performance issues.
Another solution can be the following:
select
c.[desc]
, sum (bdd.amount) as amount
, amt = (select sum (amt) from t_ind where id = c.id)
from #t_main c
left outer join t_direct bds on (bds.repid=c.id)
left outer join tm_defination_def bdd on (bdd.id = bds.sId)
where c.repId = 1000000134
group by c.id, c.[desc]
The result will be the same. Basically, instead of using of nested selects the calculating of the amt sum is performing inline per each row of the result joins. In case of large tables the performance of the second solution will be worse that the first one.
Your new left outer join is forcing some rows to be returned in the result set a few times due to multiple relations most likely. Remove your SUM and just review the returned rows and work out exactly which ones you require (maybe restrict it to on certain type of t_ind record if that is applicable??), then adjust your query accordingly.
Left Outer Join - Driving Table Row Count
A left outer join may return more rows than there are in the driving table if there are multiple matches on the join clause.
Using MS SQL-Server:
DECLARE #t1 TABLE ( id INT )
INSERT INTO #t1 VALUES ( 1 ),( 2 ),( 3 ),( 4 ),( 5 );
DECLARE #t2 TABLE ( id INT )
INSERT INTO #t2 VALUES ( 2 ),( 2 ),( 3 ),( 10 ),( 11 ),( 12 );
SELECT * FROM #t1 t1
LEFT OUTER JOIN #t2 t2 ON t2.id = t1.id
This gives:
1 NULL
2 2
2 2
3 3
4 NULL
5 NULL
There are 5 rows in the driving table (t1), but 6 rows are returned because there are multiple matches for id 2.
So if an aggregate function is used, eg SUM() etc, grouped by the driving table column(s), this will give the wrong results.
To fix this, use derived tables or sub-queries to calculate the aggregate values, as already stated.
Left Outer Join - Multiple Tables
Where there are left outer joins over multiple tables, or any join for that matter, the query generates a series of derived tables in the order of joins.
SELECT * FROM t1
LEFT OUTER JOIN t2 ON t2.col2 = <...>
LEFT OUTER JOIN t3 ON t3.col3 = <...>
This is equivalent to:
SELECT * FROM
(
SELECT * FROM t1
LEFT OUTER JOIN t2 ON t2.col2 = <...>
) dt1
LEFT OUTER JOIN t3 ON t3.col3 = <...>
Here, for both queries, the results of the 1st left outer join are put into a derived table (dt1) which is then left outer joined to the 3rd table (t3).
For left outer joins over multiple tables, the order of the tables in the join clauses is critical.
Can sombody Explains me about joins?
Inner join selects common data based on where condition.
Left outer join selects all data from left irrespective of common but takes common data from right table and vice versa for Right outer.
I know the basics but question stays when it comes to join for than 5, 8, 10 tables.
Suppose I have 10 tables to join. If I have inner join with the first 5 tables and now try to apply a left join with the 6th table, now how the query will work?
I mean to say now the result set of first 5 tables will be taken as left table and the 6th one will be considerded as Right table? Or only Fifth table will be considered as left and 6th as right? Please help me regarding this.
When joining multiple tables the output of each join logically forms a virtual table that goes into the next join.
So in the example in your question the composite result of joining the first 5 tables would be treated as the left hand table.
See Itzik Ben-Gan's Logical Query Processing Poster for more about this.
The virtual tables involved in the joins can be controlled by positioning the ON clause. For example
SELECT *
FROM T1
INNER JOIN T2
ON T2.C = T1.C
INNER JOIN T3
LEFT JOIN T4
ON T4.C = T3.C
ON T3.C = T2.C
is equivalent to (T1 Inner Join T2) Inner Join (T3 Left Join T4)
It's helpful to think of JOIN's in sequence, so the former is correct.
SELECT *
FROM a
INNER JOIN b ON b.a = a.id
INNER JOIN c ON c.b = b.id
LEFT JOIN d ON d.c = c.id
LEFT JOIN e ON e.d = d.id
Would be all the fields from a and b and c where all the ON criteria match, plus the values from d where its criteria match plus all the contents of e where all its criteria match.
I know RIGHT JOIN is perfectly acceptable, but I've found in my experience that it's unnecessary - I almost always just join things from left to right.
> Simple INNER JOIN VIEW code...
CREATE VIEW room_view
AS SELECT a.*,b.*
FROM j4_booking a INNER JOIN j4_scheduling b
on a.room_id = b.room_id;
You can apply join like this..
select a.*,b.*,c.*,d.*,e.*
from [DatabaseName].[Table_a] a
INNER JOIN [DatabaseName].[Table_b] b ON a.id = b.id
INNER JOIN [DatabaseName].[Table_c] c ON b.id=c.id
INNER JOIN [DatabaseName].[Table_d] d on c.id=d.id
INNER JOIN [DatabaseName].[Table_e] e on d.id=e.id where a.con=5 and
b.con=6
Here, at place of a.* and in where condition, you can show column(filed) which you like and according condition in where condition. You can insert more table and database as per your choice. But mind that you need to mention database name and alias if you work in different database.
Just tried the following from the Example DataBase given in W3School. Worked Fine for me.
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate, Products.ProductName, Products.ProductID
FROM Orders
INNER JOIN Products
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
Join used to combine rows from two or more tables, based on a related column between them. This example from Adventure works:
SELECT a.[EmailAddress],b.[FirstName],b.[LastName],c.[PhoneNumber],d.[Name]
FROM [Person].[EmailAddress] a
INNER JOIN [Person].[Person] b
ON a.BusinessEntityID = b.BusinessEntityID
INNER JOIN [Person].[PersonPhone] c
ON b.BusinessEntityID = c.BusinessEntityID
INNER JOIN [Person].[PhoneNumberType] d
ON c.phoneNumberTypeID = d.phoneNumberTypeID