I want to connect table with lessons with table with students
Here is my query:
SELECT *
FROM Student
JOIN (
SELECT *
FROM Lesson
JOIN Has on Has.Diid = Lesson.Diid
and Has.Name = Lesson.Name
) m
on m.CreditBookNumber = Student.CreditBookNumber
But it doesn't work. Is there a way to rewrite this?
[![enter image description here][1]][1]
First off, I would avoid the subquery here. It's superfluous at best and could cause errors to be thrown at worst. The biggest opportunity for Error that I see is that in your subquery's result set there will be two columns with the same name diid. You'll need to alias those in order for them to pick up two different names and not toss an error.
Consider instead:
SELECT *
FROM Student
JOIN Has ON
Student.CreditBookNumber = Has.CreditBookNumber
JOIN Lesson ON
Has.Diid = Lesson.Diid
and Has.Name = Lesson.Name
If you are bound and determined to do this in a subquery then you will need to list out each column and provide an alias for columns where the name collides.
SELECT *
FROM Student
JOIN (
SELECT Lesson.*,
Has.Diid as HasDiid,
Has.Name as HasName,
Has.CreditBookNumber,
Has.Gid
FROM Lesson
JOIN Has on Has.Diid = Lesson.Diid
and Has.Name = Lesson.Name
) m
on m.CreditBookNumber = Student.CreditBookNumber
But since this much more complex sql will produce identical results as the first sql above, it's really overkill.
Related
I have two scripts that work in isolation, but I don't know how to stitch them together to do this all at once.
The first script:
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
This produces a table (is that the right word?). Suppose I could save that table as 'appQuote'. I then want to run this script on it:
SELECT
ApplicationId,
STRING_AGG(YEARLYPAYAMOUNT) allPremium,
STRING_AGG(SECTIONID) allSection,
STRING_AGG(SHORTNAME) allSectionName,
FROM
appQuote
GROUP BY
ApplicationId
For storage reasons I don't want to actually save the table from the first script, I just want to get the result from the first script and immediately apply the second script to it.
This is very basic, so any guidance would help.
The relevant term is known as a derived table.
In SQL you can use the result of a query as the input to another. The "nested query" produces the derived table which is then consumed by the outer query:
Select <columns>
from (
select <columns> from table join table etc
)as TableAliasName
To get the nomenclature right, what you have are not scripts or tables, but rather two queries. When a query runs it produces a result set.
To accomplish your goal, either of these queries will work:
SELECT
ApplicationId,
STRING_AGG(YEARLYPAYAMOUNT) allPremium,
STRING_AGG(SECTIONID) allSection,
STRING_AGG(SHORTNAME) allSectionName,
FROM (
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
) appQuote
GROUP BY
ApplicationId
Here, the inner nested query is formally called a derived table, but people will often use the phrase "subquery".
The other option is a Common Table Expression (CTE):
With appQuote As (
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
)
SELECT
ApplicationId,
STRING_AGG(YEARLYPAYAMOUNT) allPremium,
STRING_AGG(SECTIONID) allSection,
STRING_AGG(SHORTNAME) allSectionName,
FROM
appQuote
GROUP BY
ApplicationId
Finally, you could also create a View from the first query:
CREATE View AppQuote As
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
A view is not just a query; it will actually become part of the database, such that you can use it in many of the same ways you would use a table saved on disk, and then the second query in the original question will run unmodified.
I have two tables (PlayerDTO and ClubDTO) and am using a JOIN to fetch data as follows:
SELECT * FROM PlayerDTO AS pl
INNER JOIN ClubDTO AS cl
ON pl.currentClub = cl.id
WHERE cl.nation = 7
This returns the correct rows from PlayerDTO, but in every row the id column has been changed to the value of the currentClub column (eg instead of pl.id 3,456 | pl.currentClub 97, it has become pl.id 97 | pl.currentClub 97).
So I tried the query listing all the columns by name instead of Select *:
SELECT pl.id, pl.nationality, pl.currentClub, pl.status, pl.lastName FROM PlayerDTO AS pl
INNER JOIN ClubDTO AS cl
ON pl.currentClub = cl.id
WHERE cl.nation = 7
This works correctly and doesn’t change any values.
PlayerDTO has over 100 columns (I didn’t list them all above for brevity, but I included them all in the query) but obviously I don’t want to write every column name in every query.
So could somebody please explain why Select * changes the id value and what I need to do to make it work correctly? All my tables have a column called id, is that something to do with it?
SELECT *... is, according to the docs...
shorthand for “select all columns.” (Source: Dev.MySQL.com
Both your tables have id columns, so which should be returned? It's not indicated, so MySQL makes a guess. So select what you want to select...
SELECT pl.id, *otherfieldsyouwant* FROM PlayerDTO AS pl...
Or...
SELECT pl.* FROM PlayerDTO AS pl...
Typically, SELECT * is bad form. The odds you are using every field is astronomically low. And the more data you pull, the slower it is.
New to SQL but I want to be able to optimize my query by bringing just the right amount of data. I am doing a left join on CS Rep Name and WE, which are two columns present in both tables. I find that if I don't bring in CS Rep Name and WE in the TECDR table, the query would error. Is there a workaround to this? Since it is a left join, I don't need redundant data.
SELECT *
FROM Tish_Email_CSAT_Dump AS TECD
LEFT JOIN (SELECT CS_Rep_Name,
Team_Leader,
Operations_Manager,
Tenure,
WE,
FileName
FROM Tish_Email_CSAT_Dump_Roster) AS TECDR
ON TECD.CS_Rep_Name = TECDR.CS_Rep_Name
AND TECD.WE = TECDR.WE
When you embed a SELECT inside a query in place of a table, the result of a select (projection) behave like a table visible only inside the query.
In your case, the join is the same as if there were a table called TECDR with the columns that you select. Hence, if you leave out some columns of Tish_Email_CSAT_Dump_Roster from your SELECT, these columns would not be available for joining or selection.
However, in your case this is unnecessary: all you need to do is joining to the underlying table, like this:
SELECT
TECD.*
, TECDR.Team_Leader
, TECDR.Operations_Manager
, TECDR.Tenure
, TECDR.FileName
FROM Tish_Email_CSAT_Dump AS TECD
LEFT JOIN Tish_Email_CSAT_Dump_Roster AS TECDR
ON TECD.CS_Rep_Name = TECDR.CS_Rep_Name AND TECD.WE = TECDR.WE
select
<place the columns you want here>
from
Tish_Email_CSAT_Dump as TECD
Left join Tish_Email_CSAT_Dump_Roster as TECDR
On TECD.CS_Rep_Name = TECDR.CS_Rep_Name and TECD.WE = TECDR.WE
Hope the following helps or else please share the query that errors:
select TECD.Column1, TECD.Column2, TECDR.Column1, TECDR.Column2
from Tish_Email_CSAT_Dump as TECD
Left join Tish_Email_CSAT_Dump_Roster as TECDR
On TECD.CS_Rep_Name = TECDR.CS_Rep_Name and TECD.WE = TECDR.WE
SELECT Title
FROM movie
WHERE Movie_no = (SELECT Movie_no
FROM Customer
INNER JOIN issues ON customer.`Cus_id`=issues.`Cus_id`
WHERE NAME = 'Shyam')
No. You just need to use IN or ANY:
SELECT Title
FROM movie
WHERE Movie_no IN (SELECT Movie_no
FROM Customer INNER JOIN
issues
ON customer.Cus_id = issues.Cus_id
WHERE NAME = 'Shyam'
);
I mean, you might need to normalize your data for other reasons, but a subquery returning more than one value would not be such a reason. And, your data structure seems reasonable, based on this one query.
Despite going through every material I could possibly find on the internet, I haven't been able to solve this issue myself. I am new to MS Access and would really appreciate any pointers.
Here's my problem - I have three tables
Source1084 with columns - Department, Sub-Dept, Entity, Account, +few more
R12CAOmappingTable with columns - Account, R12_Account
Table4 with columns - R12_Account, Department, Sub-Dept, Entity, New Dept, LOB +few more
I have a total of 1084 records in Source and the result table must also contain 1084 records. I need to draw a table with all the columns from Source + R12_account from R12CAOmappingTable + all columns from Table4.
Here is the query I wrote. This yields the right columns but gives me more or less number of records with interchanging different join options.
SELECT rmt.r12_account,
srb.version,
srb.fy,
srb.joblevel,
srb.scenario,
srb.department,
srb.[sub-department],
srb.[job function],
srb.entity,
srb.employee,
table4.lob,
table4.product,
table4.newacct,
table4.newdept,
srb.[beg balance],
srb.jan,
srb.feb,
srb.mar,
srb.apr,
srb.may,
srb.jun,
srb.jul,
srb.aug,
srb.sep,
srb.oct,
srb.nov,
srb.dec,
rmt.r12_account
FROM (source1084 AS srb
LEFT JOIN r12caomappingtable AS rmt
ON srb.account = rmt.account)
LEFT JOIN table4
ON ( srb.department = table4.dept )
AND ( srb.[sub-department] = table4.subdept )
AND ( srb.entity = table4.entity )
WHERE ( ( ( srb.[sub-department] ) = table4.subdept )
AND ( ( srb.entity ) = table4.entity )
AND ( ( rmt.r12_account ) = table4.r12_account ) );
In this simple example, Table1 contains 3 rows with unique fld1 values. Table2 contains one row, and the fld1 value in that row matches one of those in Table1. Therefore this query returns 3 rows.
SELECT *
FROM
Table1 AS t1
LEFT JOIN Table2 AS t2
ON t1.fld1 = t2.fld1;
However if I add the WHERE clause as below, that version of the query returns only one row --- the row where the fld1 values match.
SELECT *
FROM
Table1 AS t1
LEFT JOIN Table2 AS t2
ON t1.fld1 = t2.fld1
WHERE t1.fld1 = t2.fld1;
In other words, that WHERE clause counteracts the LEFT JOIN because it excludes rows where t2.fld1 is Null. If that makes sense, notice that second query is functionally equivalent to this ...
SELECT *
FROM
Table1 AS t1
INNER JOIN Table2 AS t2
ON t1.fld1 = t2.fld1;
Your situation is similar. I suggest you first eliminate the WHERE clause and confirm this query returns at least your expected 1084 rows.
SELECT Count(*) AS CountOfRows
FROM (source1084 AS srb
LEFT JOIN r12caomappingtable AS rmt
ON srb.account = rmt.account)
LEFT JOIN table4
ON ( srb.department = table4.dept )
AND ( srb.[sub-department] = table4.subdept )
AND ( srb.entity = table4.entity );
After you get the query returning the correct number of rows, you can alter the SELECT list to return the columns you want. But the columns aren't really the issue until you can get the correct rows.
Without knowing your tables values it is hard to give a complete answer to your question. The issue that is causing you a problem based on how you described it. Is more then likely based on the type of joins you are using.
The best way I found to understand what type of joins you should be using would referencing a Venn diagram explaining the different type of joins that you can use.
Jeff Atwood also has a really good explanation of SQL joins on his site using the above method as well.
Best to just use the query builder. Drop in your main table. Choose the columns you want. Now for any of the other lookup values then simply drop in the other tables, draw the join line(s), double click and use a left join. You can do this for 2 or 30 columns that need to "grab" or lookup other values from other tables. The number of ORIGINAL rows in the base table returned should ALWAYS remain the same.
So just use the query builder and follow the above.
The problem with your posted SQL is you NESTED the joins inside (). Don't do that. (or let the query builder do this for you – they tend to be quite messy but will also work).
Just use this:
FROM source1084 AS srb
LEFT JOIN r12caomappingtable AS rmt
ON srb.account = rmt.account
LEFT JOIN table4
ON ( srb.department = table4.dept )
AND ( srb.[sub-department] = table4.subdept )
AND ( srb.entity = table4.entity )
As noted, I don't see why you are "repeating" the conditions again in the where clause.