--Query1
SELECT TransactionDetails.Transactions.TransactionId
, TransactionDetails.Transactions.CustomerId
, TransactionDetails.Transactions.TransactionType
, TransactionDetails.Transactions.DateEntered
, TransactionDetails.Transactions.RelatedProductId
, CustomerDetails.CustomerProducts.CustomerFinancialProductId
, CustomerDetails.CustomerProducts.CustomerId AS 'CustomerProducts--CustomerID'
, CustomerDetails.CustomerProducts.FinancialProductId
, CustomerDetails.CustomerProducts.AmountToCollect
FROM TransactionDetails.Transactions
INNER JOIN CustomerDetails.Customers ON TransactionDetails.Transactions.CustomerId = CustomerDetails.Customers.CustomerID
INNER JOIN CustomerDetails.CustomerProducts ON CustomerDetails.Customers.CustomerID = CustomerDetails.CustomerProducts.CustomerId
WHERE TransactionId = 2
ORDER BY CustomerFinancialProductId
--Query2
SELECT TransactionDetails.Transactions.TransactionId
, TransactionDetails.Transactions.CustomerId
, TransactionDetails.Transactions.TransactionType
, TransactionDetails.Transactions.DateEntered
, TransactionDetails.Transactions.RelatedProductId
, CustomerDetails.CustomerProducts.CustomerFinancialProductId
, CustomerDetails.CustomerProducts.CustomerId AS 'CustomerProducts--CustomerID'
, CustomerDetails.CustomerProducts.FinancialProductId
, CustomerDetails.CustomerProducts.AmountToCollect
FROM TransactionDetails.Transactions
INNER JOIN CustomerDetails.FinancialProducts ON TransactionDetails.Transactions.RelatedProductId = CustomerDetails.FinancialProducts.ProductId
INNER JOIN CustomerDetails.CustomerProducts ON CustomerDetails.FinancialProducts.ProductId = CustomerDetails.CustomerProducts.FinancialProductId
WHERE TransactionId = 2
ORDER BY CustomerFinancialProductId
Here are two queries that i have been given to compare. it asks which one navigates better ir should be the correct one used?
I know that the first query returns only 1 row where as the second returns 11 rows.
Also Query 1 navigates through Transactions to Customers where it's using ProductID as it's column in each. the 2nd query goes from Transactions to FinancialProducts where the join is on RelatedProductID in the transactions table and productID in the FinancialProducts table
Both queries then end in the same table with the same columns chosen in that table.
Lastly the FinancialProductID is 22 in the first query and in the 2nd query all 11 rows have a financialProductID of 22
ACTUAL QUESTION: WHICH ONE IS THE CORRECT FORM OF NAVIGATING TO THE TABLE
The question that you have asked is a business question about the meaning of the data.
It looks like both versions of the query are properly joining the tables together. You understand your business domain, whereas the rest of us do not.
That said, based on the names of the tables, the first version "makes sense" to me. A transaction has a customer and customers have products. So, if you want all the products for a customer on a transaction, then the first would seem to do that.
I don't know what role FinancialProducts plays in this database. It is quite possible that the second version "makes more sense" for this application. If you are using this database, you should learn what these tables are.
Related
I have been working on this script for a while and have reached a dead end. The script works but unfortunately produces duplicates. My script joins two different tables across databases on a state_issue_teacher_id key and then produces the output. I have checked both tables and the row counts are the same and the join should match records perfectly but evidently there is a problem with my key or the way I'm joining to the table and my output is coming back partially incorrect. I've also tried concatenating attributes to make a unique key and join the tables but still producing incorrect results.
Here is my script:
SELECT
LTRIM(RTRIM(rt.year_time)) AS 'year_time' ,
LTRIM(RTRIM(rt.state_issue_teacher_id)) AS state_issue_teacher_id ,
LTRIM(RTRIM(rt.district_code)) AS district_code ,
rt.district_name ,
rt.school_name ,
LTRIM(RTRIM(rt.assignment_code)) AS assignment_code ,
rt.assignment_desc ,
LTRIM(RTRIM(rt.position_code)) AS position_code ,
rt.position_desc ,
LTRIM(RTRIM(rt.last_name)) AS last_name ,
LTRIM(RTRIM(rt.first_name)) AS first_name ,
LTRIM(RTRIM(rt.total_salary)) AS total_salary ,
rt.assign_fte ,
LTRIM(RTRIM(rt.school_code)) AS school_code ,
rt.fte
FROM staging.dbo.rt AS rt
LEFT JOIN ( SELECT LTRIM(RTRIM(dti.year)) AS year ,
LTRIM(RTRIM(dt.teacher_id)) AS teacher_id ,
LTRIM(RTRIM(db.district_code)) AS district_code ,
db.district_name ,
LTRIM(RTRIM(dt.last_name)) AS last_name ,
LTRIM(RTRIM(dt.first_name)) AS first_name ,
LTRIM(RTRIM(da.assignment_code)) AS assignment_code ,
LTRIM(RTRIM(dp.position_code)) AS position_code ,
dre.race_ethnicity_code ,
LTRIM(RTRIM(SUBSTRING(db.school_code,10,4))) AS school_code ,
da.assignment_desc ,
dp.position_desc ,
fs.total_fte
FROM mart.dbo.fact_s AS fs
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_building
AS db ON fs.building_key = db.building_key
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_teacher
AS dt ON fs.teacher_key = dt.teacher_key
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_assignment
AS da ON fs.assignment_key = da.assignment_key
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_race_ethnicity
AS dre ON dt.race_ethnicity_key = dre.race_ethnicity_key
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_gender
AS dg ON dt.gender_key = dg.gender_key
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_time
AS dti ON fs.time_key = dti.time_key
LEFT OUTER JOIN mart.dbo.fact_s.dbo.dim_position
AS dp ON fs.position_key = dp.position_key
WHERE dti.year = '2012'
) raw ON rt.state_issue_teacher_id = raw.teacher_id
AND rt.year_time = raw.year
AND rt.last_name = raw.last_name
AND rt.first_name = raw.first_name
AND rt.district_code = raw.district_code
AND rt.position_code = raw.position_code
AND rt.school_code = RAW.school_code
AND rt.assignment_code = raw.assignment_code
WHERE rt.year_time = '2012'
ORDER BY rt.last_name, rt.first_name
The output that I'm getting is:
The fte for the combined teachers assignments should add up to 1. But teachers that have the same assignment_code/desc with multiple partial assignments are producing duplicates. Example: Jane Doe appears 4 times with a total fte of 2.0 instead of 2 times with the correct total of 1.0. The output should read as follows.
You appear to be getting the duplicates for part-time teachers that have multiple assignments, with all the descriptions of the assignment being the same. This is quite clear from the first four rows of your actual output versus the first two of the desired output.
I wonder why you would have those duplicates to begin with. However, they are in the fact table so there must be something important (I suppose two part-time guidance counselors are funded rather than one full-time one). Does the fact table really have exact duplicate records in this case? If not, the fields that are not duplicated may suggest an additional join key that will fix the problem.
You need to get rid of the Cartesian product produced by this join condition: rt.assignment_code = raw.assignment_code.
Apart from finding a better join key, I can think of two ways to fix this. The first would be to create a really unique id for the positions. Perhaps in your data structure you know of one. Or, you could use row_number() to add a sequence number for people who have multiple positions.
The other way would be to eliminate the duplicates on one side or the other. For instance, you might aggregate rt to eliminate such duplicates.
I am having a slow brain day...
The tables I am joining:
Policy_Office:
PolicyNumber OfficeCode
1 A
2 B
3 C
4 D
5 A
Office_Info:
OfficeCode AgentCode OfficeName
A 123 Acme
A 456 Acme
A 789 Acme
B 111 Ace
B 222 Ace
B 333 Ace
... ... ....
I want to perform a search to return all policies that are affiliated with an office name. For example, if I search for "Acme", I should get two policies: 1 & 5.
My current query looks like this:
SELECT
*
FROM
Policy_Office P
INNER JOIN Office_Info O ON P.OfficeCode = O.OfficeCode
WHERE
O.OfficeName = 'Acme'
But this query returns multiple rows, which I know is because there are multiple matches from the second table.
How do I write the query to only return two rows?
SELECT DISTINCT a.PolicyNumber
FROM Policy_Office a
INNER JOIN Office_Info b
ON a.OfficeCode = b.OfficeCode
WHERE b.officeName = 'Acme'
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Simple join returns the Cartesian multiplication of the two sets and you have 2 A in the first table and 3 A in the second table and you probably get 6 results. If you want only the policy number then you should do a distinct on it.
(using MS-Sqlserver)
I know this thread is 10 years old, but I don't like distinct (in my head it means that the engine gathers all possible data, computes every selected row in each record into a hash and adds it to a tree ordered by that hash; I may be wrong, but it seems inefficient).
Instead, I use CTE and the function row_number(). The solution may very well be a much slower approach, but it's pretty, easy to maintain and I like it:
Given is a person and a telephone table tied together with a foreign key (in the telephone table). This construct means that a person can have more numbers, but I only want the first, so that each person only appears one time in the result set (I ought to be able concatenate multiple telephone numbers into one string (pivot, I think), but that's another issue).
; -- don't forget this one!
with telephonenumbers
as
(
select [id]
, [person_id]
, [number]
, row_number() over (partition by [person_id] order by [activestart] desc) as rowno
from [dbo].[telephone]
where ([activeuntil] is null or [activeuntil] > getdate()
)
select p.[id]
,p.[name]
,t.[number]
from [dbo].[person] p
left join telephonenumbers t on t.person_id = p.id
and t.rowno = 1
This does the trick (in fact the last line does), and the syntax is readable and easy to expand. The example is simple but when creating large scripts that joins tables left and right (literally), it is difficult to avoid that the result contains unwanted duplets - and difficult to identify which tables creates them. CTE works great for me.
I have two tables that I try to join over one field and it gives me different results in two queries that should give same results. Queries are:
SELECT * FROM tblCustomer tca
WHERE tca.PhoneNumber IN(
SELECT ts.SubscriptionNumber FROM sub.tblSubscription ts
WHERE ts.ServiceTypeID=4
AND ts.SourceID=-1
)
and
SELECT tca.*
FROM sub.tblSubscription ts
inner JOIN tblCustomer tca
ON ts.SubscriptionNumber = tca.PhoneNumber
WHERE ts.ServiceTypeID = 4
AND ts.SourceID = -1
How is this possible?
I'm assuming a customer can have multiple subscriptions, right? Let's assume you have 5 customers, each with 2 subscriptions...
When doing a SELECT ... FROM Customer WHERE IN (Subscription), you will receive 5 customer records, because each of those 5 customers are in fact in the subscription table, even though the subscription table will have 10 records. You are inherently asking the database for the data from one table, where the value of one of it's fields exists in another table. So it will only return the distinct records in the FROM table, irrespective of the amount of data in the WHERE IN table.
On the other hand, INNER JOINing the Customer table with the subscription table will return 5 customers x 2 subscriptions each = 10 records. By JOINing the tables you are asking the database for ALL the data in each table, where the data is matched up against specific fields.
So yes, the 2 queries will definitely give you different results.
Hi am I am creating a database which allows users to make a reservation to a restaurant. Below is my data model for the database.
My question is i am a little confused with how i would check for tables that are available on a given night. The restaurant has 15 tables for any night with 4 people to a table (Groups can be 4 - 6 big, groups larger than 4 will take up two tables).
How would i query the database to return the tables which are available on a given night.
Thanks.
EDIT::
This is what i have tried. (Some of it is pseudo as i am not quite sure how to do it)
SELECT tables.table_id
FROM tables
LEFT JOIN table_allocation
ON tables.table_id = table_allocation.table_id
WHERE table_allocation.table_id is NULL;
This returns the well empty rows as it is checking for the none presence of the table. I am not quite sure how i would do the date bit test.
To find TABLE rows that have no TABLE_ALLOCATION rows on a given THEMED_NIGHT.TEME_NIGHT_DATE, you should be able to do something like this:
SELECT *
FROM TABLES
WHERE
TABLE_ID NOT IN (
SELECT TABLE_ALLOCATION.TABLE_ID
FROM
TABLE_ALLOCATION
JOIN RESERVATION
ON TABLE_ALLOCATION.RESERVATION_ID = RESERVATION.RESERVATION_ID
JOIN THEMED_NIGHT
ON RESERVATION.THEME_ID = THEMED_NIGHT.THEME_ID
WHERE
THEME_NIGHT_NAME = :the_date
)
In plain English:
Join TABLE_ALLOCATION, RESERVATION and THEMED_NIGHT and accept only those that are on the given date (:the_date).
Discard the TABLE rows that are related to the tuples above (NOT IN).
Those TABLE rows that remain are free for the night.
Try:
SELECT tables.table_id
FROM tables t
WHERE NOT EXISTS
(SELECT NULL
FROM table_allocation a
JOIN reservation r
ON a.reservation_id = r.reservation_id and
r.`TIME` between :Date and :Date+1
WHERE t.table_id = a.table_id)
Note: will only return tables that are not booked at any point on the day in question.
I am new to SQL. I am trying to select some of the fields from 2 of 3 joined tables and all of the fields from a 3rd table. Other than specifying each individual field from the Pr table, is the a simpler way to SELECT individual fields from two of the tables and SELECT * from the 3rd table. My current query is below. This is an exercise from a book. If the 3rd table contained more fields this method would become very cumbersome.
SELECT Lo.City ,
Em.FirstName ,
Em.LastName ,
Pr.EmpID ,
Pr.YearlySalary ,
Pr.MonthlySalary ,
Pr.HourlyRate
FROM Location AS Lo
INNER JOIN Employee AS Em ON Lo.LocationID = Em.LocationID
INNER JOIN PayRates AS Pr ON Em.EmpID = Pr.EmpID
Yes, you can use Pr.* to select all columns from the table aliased Pr.
This is widely discouraged in production code however as if the table definition changes your query can suddenly start bringing back loads of irrelevant data that is not needed.