SQL SERVER 2008 - joins - sql

I have three tables that I'm trying to join to get the necessary data. Here they are...
*TblComp* *TblCompParent* *tblCompProcesses*
CompID CompBillingID CompID
CompBillingID Capacity1 CompProcessID
Capacity2
So what I'm trying to do with these three tables is....
Select tblCompParent.Capacity1, tblCompParent.Capacity2, CompProcessID
My problem is this...In tblComp there are 351 values - so i start off by joining tblComp and tblCompparent and SELECTING tblCompparent.capacity1, tblcompparent.capacity2, the query looks like this...
SELECT dbo.tblComp.CompID, dbo.tblCompParents.Capacity1, dbo.tblCompParents.Capacity2
FROM dbo.tblCompParents INNER JOIN
dbo.tblComp ON dbo.tblCompParents.CompBillingID = dbo.tblComp.CompBillingID
And this works fine, it's when I try to join tblCompProcess to pull the CompProcessID is when I get like 580 records. I'm not sure what can of join I have to do on tblCompprocess to select only one CompProcessID per compID.
And it seems like i have to use tblComp otherwise I'll have no way of joining tblCompProcess.
EDIT1:
SELECT dbo.tblComp.CompID, dbo.tblCompParents.Capacity1, dbo.tblCompParents.Capacity2, tblCompProcess.compprocessID
FROM dbo.tblCompParents INNER JOIN
dbo.tblComp ON dbo.tblCompParents.CompBillingID = dbo.tblComp.CompBillingID
Inner Join dbo.tblCompprocess on tblCompProcess.CompID = tblComp.CompID

You don't show us the whole data model so I don't know exactly what is going on but clearly tblCompProcesses has more than one row in your join. I would fix it like this:
SELECT dbo.tblComp.CompID, dbo.tblCompParents.Capacity1, dbo.tblCompParents.Capacity2, x.compprocessID
FROM dbo.tblCompParents
INNER JOIN dbo.tblComp ON dbo.tblCompParents.CompBillingID = dbo.tblComp.CompBillingID
INNER JOIN (SELECT DISTINCT CompID, compprocessID
FROM dbo.tblCompprocess) X on x.CompID = tblComp.CompID

Related

Transact SQL - Join one table with other two

I have a table that is for PaymentRequest (PR), each PR table has two forms of pay, a WorkProgress, and a AdvanceByWarranty, the relation is like this:
I Need to create a report to get all the payment made in that (PR), and some other fields between them
The sql that I was using to join PaymentRequest with WorkProgress is this, and it works, it returns the WorkProgress of that payment
To get the Advances by warranty I use this, it also works, returns 2 Advances, as it should be
But, when I mix both, it doesnt return 3 rows, as it should be, it returns two. The result is this
I was expecting something like this (With shorter names)
How can i get the expected query?
Edit:
The sql to get the expected query is this
select
pr.ProjectId, pr.NumberPaymentState,
wp.ToCollectAmmount as WPAmmount, wp.ToCollectPercent as WPPercent,
null as AWAmmount, null as AWPercent
from PaymentRequests pr
left join WorkProgresses wp on (wp.ProjectId = pr.ProjectId and wp.NumberPaymentState = pr.NumberPaymentState)
union all
select
pr.ProjectId, pr.NumberPaymentState,
null as WPAmmount, null as WPPercent,
aw.ToCollectAmmount as AWAmmount, aw.ToCollectPercent as AWPercent
from PaymentRequests pr
left join AdvanceByWarranties aw on (aw.ProjectId = pr.ProjectId and aw.NumberPaymentState = pr.NumberPaymentState)
You might have wanted what you show, but it doesn't work like this.
Just use UNION ALL between your first two queries, and rename the columns accordingly. Here is some pseudocode hybrid to guide you:
select keycols, workercols, null as advancecols
from pr join worker
union all
select keycols, null as workercols, advancecols
from pr join advancecols

Access SQL query without duplicate results

I made a query and wanted to not have any duplicates but i got some times 3 duplicates and when i used DISTINCT or DISTINCTROW i got only 2 duplicates.
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
(((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN Irregular_Events AS ie
ON f.flight_code = ie.flight_code)
LEFT JOIN Delay_Event AS de
ON ie.IE_code = de.delay_code;
had to use LEFT JOIN because when i used INNER JOIN i missed some of the things i wanted to show because i wanted to see all the flights and not only the flights that got delayed or canceled.
This is the results when i used INNER JOIN, you can see only the flights that have the status "ביטול" or "עיכוב" and that is not what i wanted.
[the results with LEFT JOIN][2]
[2]: https://i.stack.imgur.com/cgE2G.png
and when i used DISTINCT where you see the rows with the NUMBER 6 on the first column it appear only two times
IMPORTANT!
I just checked my query and all the tables i use there and i saw my problem but dont know how to fix it!
in the table Irregular_Events i have more the one event for flights 3,6 and 8 and that is why when i use LEFT JOIN i see more even thou i use distinct, please give me some help!
Not entirely sure without seeing the table structure, but this might work:
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN
(
SELECT
ie.flight_code,
de1.actual_takeoff_date,
de1.actual_takeoff_time
FROM
Irregular_Events ie
INNER JOIN Event AS de1
ON ie.IE_code = de1.delay_code
) AS de
ON f.flight_code = de.flight_code
It is hard to tell what is the problem with your query without any sample of the output, and without any description of the structure of your tables.
But your problem is that your are querying from the flights table, which [I assume] can be linked to multiple irregular_events, which can possibly also be linked to multiple delay_event.
If you want to get only one row per flight, you need to make sure your joins return only one row too. Maybe you can do it by adding one more condition to the join, or by adding a condition in a sub-query.
EDIT
You could try to add a GROUP BY to the query:
GROUP BY
f.flight_code,
f.status,
a.airport_name,
a1.airport_name;

Timeout running SQL query

I'm trying to using the aggregation features of the django ORM to run a query on a MSSQL 2008R2 database, but I keep getting a timeout error. The query (generated by django) which fails is below. I've tried running it directs the SQL management studio and it works, but takes 3.5 min
It does look it's aggregating over a bunch of fields which it doesn't need to, but I wouldn't have though that should really cause it to take that long. The database isn't that big either, auth_user has 9 records, ticket_ticket has 1210, and ticket_watchers has 1876. Is there something I'm missing?
SELECT
[auth_user].[id],
[auth_user].[password],
[auth_user].[last_login],
[auth_user].[is_superuser],
[auth_user].[username],
[auth_user].[first_name],
[auth_user].[last_name],
[auth_user].[email],
[auth_user].[is_staff],
[auth_user].[is_active],
[auth_user].[date_joined],
COUNT([tickets_ticket].[id]) AS [tickets_captured__count],
COUNT(T3.[id]) AS [assigned_tickets__count],
COUNT([tickets_ticket_watchers].[ticket_id]) AS [tickets_watched__count]
FROM
[auth_user]
LEFT OUTER JOIN [tickets_ticket] ON ([auth_user].[id] = [tickets_ticket].[capturer_id])
LEFT OUTER JOIN [tickets_ticket] T3 ON ([auth_user].[id] = T3.[responsible_id])
LEFT OUTER JOIN [tickets_ticket_watchers] ON ([auth_user].[id] = [tickets_ticket_watchers].[user_id])
GROUP BY
[auth_user].[id],
[auth_user].[password],
[auth_user].[last_login],
[auth_user].[is_superuser],
[auth_user].[username],
[auth_user].[first_name],
[auth_user].[last_name],
[auth_user].[email],
[auth_user].[is_staff],
[auth_user].[is_active],
[auth_user].[date_joined]
HAVING
(COUNT([tickets_ticket].[id]) > 0 OR COUNT(T3.[id]) > 0 )
EDIT:
Here are the relevant indexes (excluding those not used in the query):
auth_user.id (PK)
auth_user.username (Unique)
tickets_ticket.id (PK)
tickets_ticket.capturer_id
tickets_ticket.responsible_id
tickets_ticket_watchers.id (PK)
tickets_ticket_watchers.user_id
tickets_ticket_watchers.ticket_id
EDIT 2:
After a bit of experimentation, I've found that the following query is the smallest that results in the slow execution:
SELECT
COUNT([tickets_ticket].[id]) AS [tickets_captured__count],
COUNT(T3.[id]) AS [assigned_tickets__count],
COUNT([tickets_ticket_watchers].[ticket_id]) AS [tickets_watched__count]
FROM
[auth_user]
LEFT OUTER JOIN [tickets_ticket] ON ([auth_user].[id] = [tickets_ticket].[capturer_id])
LEFT OUTER JOIN [tickets_ticket] T3 ON ([auth_user].[id] = T3.[responsible_id])
LEFT OUTER JOIN [tickets_ticket_watchers] ON ([auth_user].[id] = [tickets_ticket_watchers].[user_id])
GROUP BY
[auth_user].[id]
The weird thing is that if I comment out any two lines in the above, it runs in less that 1s, but it doesn't seem to matter which lines I remove (although obviously I can't remove a join without also removing the relevant SELECT line).
EDIT 3:
The python code which generated this is:
User.objects.annotate(
Count('tickets_captured'),
Count('assigned_tickets'),
Count('tickets_watched')
)
A look at the execution plan shows that SQL Server is first doing a cross-join on all the table, resulting in about 280 million rows, and 6Gb of data. I assume that this is where the problem lies, but why is it happening?
SQL Server is doing exactly what it was asked to do. Unfortunately, Django is not generating the right query for what you want. It looks like you need to count distinct, instead of just count: Django annotate() multiple times causes wrong answers
As for why the query works that way: The query says to join the four tables together. So say an author has 2 captured tickets, 3 assigned tickets, and 4 watched tickets, the join will return 2*3*4 tickets, one for each combination of tickets. The distinct part will remove all the duplicates.
what about this?
SELECT auth_user.*,
C1.tickets_captured__count
C2.assigned_tickets__count
C3.tickets_watched__count
FROM
auth_user
LEFT JOIN
( SELECT capturer_id, COUNT(*) AS tickets_captured__count
FROM tickets_ticket GROUP BY capturer_id ) AS C1 ON auth_user.id = C1.capturer_id
LEFT JOIN
( SELECT responsible_id, COUNT(*) AS assigned_tickets__count
FROM tickets_ticket GROUP BY responsible_id ) AS C2 ON auth_user.id = C2.responsible_id
LEFT JOIN
( SELECT user_id, COUNT(*) AS tickets_watched__count
FROM tickets_ticket_watchers GROUP BY user_id ) AS C3 ON auth_user.id = C3.user_id
WHERE C1.tickets_captured__count > 0 OR C2.assigned_tickets__count > 0
--WHERE C1.tickets_captured__count is not null OR C2.assigned_tickets__count is not null -- also works (I think with beter performance)

SQL Query not working

I have these four tables:
SELECT [B_Key]
,[B_FiscalYear]
,[B_OrgCode]
,[B_SubObject]
,[B_Explanation]
,[B_CIPrefNo]
,[B_OrgBudgetAmt]
,[B_BudgetAmt]
,[B_Initials]
FROM [NAOLI].[dbo].[BudgetTbl]
SELECT [F_Fykey]
,[F_FiscalYear]
,[F_Year]
FROM [NAOLI].[dbo].[codeFiscalYearTbl]
SELECT [O_OrgKey]
,[O_OrgCode]
,[O_OrgDesc]
,[O_Divisions]
FROM [NAOLI].[dbo].[codeOrgCodeTbl]
SELECT [S_SubKey]
,[S_SubObject]
,[S_SubDescrip]
FROM [NAOLI].[dbo].[codeSubObjectTbl]
I need to combine different pieces of the information in these tables in order to make the table of information below:
[B_FiscalYear]
,[O_OrgCode]
,[O_OrgDesc]
,[S_SubObject]
,[S_SubDescrip]
,[B_BudgetAmt]
,[B_Initials]
,[B_CIPrefNo]
,[B_OrgBudgetAmt]
I tried the below query but it returns 0 of the 20750 records.. How do I accomplish this? thanks
SELECT [B_FiscalYear]
,[B_OrgCode]
,[O_OrgDesc]
,[B_SubObject]
,[S_SubDescrip]
,[B_BudgetAmt]
,[B_Initials]
,[B_CIPrefNo]
,[B_OrgBudgetAmt]
INTO dbo.BudgetsTbl
FROM [BudgetTbl] BT, [codeFiscalYearTbl] FY, [codeOrgCodeTbl] OC, [codeSubObjectTbl] SO
WHERE BT.B_FiscalYear = FY.F_Year and BT.B_OrgCode = OC.O_OrgCode and BT.B_SubObject = SO.S_SubObject
The join should be like this:
SELECT [B_FiscalYear]
,[B_OrgCode]
,[O_OrgDesc]
,[B_SubObject]
,[S_SubDescrip]
,[B_BudgetAmt]
,[B_Initials]
,[B_CIPrefNo]
,[B_OrgBudgetAmt]
FROM BudgetTbl BT
JOIN codeFiscalYearTbl FY ON BT.B_FiscalYear = FY.F_Year
JOIN codeOrgCodeTbl OC ON BT.B_OrgCode = OC.O_OrgCode
JOIN codeSubObjectTbl SO ON BT.B_SubObject = SO.S_SubObject
You can look at http://sqlfiddle.com/#!3/8ff6b/7 for more info.
Also you can add left joins if needed.
The proper join syntax is:
SELECT [B_FiscalYear], [B_OrgCode], [O_OrgDesc], [B_SubObject], [S_SubDescrip],
[B_BudgetAmt], [B_Initials], [B_CIPrefNo], [B_OrgBudgetAmt]
INTO dbo.BudgetsTbl
FROM BudgetTbl BT join
codeFiscalYearTbl FY
on BT.B_FiscalYear = FY.F_Year join
codeOrgCodeTbl OC
on BT.B_OrgCode = OC.O_OrgCode join
codeSubObjectTbl SO
on BT.B_SubObject = SO.S_SubObject
Presumably, one or more of your lookup tables are empty. If you want all rows, replace the "join" with "left outer join" in the above query.

sql query. Associated with multiple tables

Having this problem, I don `t know how to pull data from multiple tables. I tried to use INNER JOIN and UNION.
Here is what I came so far:
select `name_ganre` from `teleprogram`.`ganres`
where `idganre`=any(select `idganre` from `teleprogram`.`ganre-transfer`
where `idtransfer`=any(select `idtransfer` from `teleprogram`.`broadcasting`));
select `name_channel` from `teleprogram`.`channel`
where `idchannel`= any(select `idchannel` from `teleprogram`.`broadcasting`);
I need to bring in one column name of the channel. And another name for the genre.
broadcasting
rows: idtransfer, idchannel
transfer
rows: idtransfer, name_transfer
ganre-transfer
rows: idganre, idtransfer
ganre
rows: idganre, name_ganre
channels
rows: idchannel, name_channel
I'm trying to get the data through broadcasting. May be simplified?
After the query: name_channel, name_ganre
Thank you!
The query that you need is this:
select c.name_channel, g.name_ganre
from channels c
inner join broadcasting b on b.idchannel = c.idchannel
inner join ganre-transfer gt on gt.idtransfer = b.idtransfer
inner join ganre g on g.idganre = gt.idganre
You can see how INNER JOIN works HERE!