SQL- Add Missing data in Left outer joing query - sql

I have following data
Components
componentid title
1 houseRent
2 medical
3 Travelling Allowance
empPayrollMaster
MasterID EmployeeID SalaryMonthID
1 101 1
2 102 1
3 103 1
empPayrollDetail
DetailID MasterID ComponentID amount
1 1 1 100
2 1 2 500
3 2 1 300
4 2 3 250
5 3 1 150
6 3 2 350
7 3 3 450
Required Output
EmployeeID MasterID ComponentID amount
101 1 1 100
101 1 2 500
101 1 3 0
102 2 1 300
102 1 2 0
102 2 3 250
103 3 1 150
103 3 2 350
103 3 3 450
To get the required output if i do left outer join between components and empPayrollDetail I get null in EmployeeID and MasterID and amount Columns. How to modify left join to get the required output

You need to do a CROSS JOIN on Components and empPayrollMaster to generate first all combination of employees and components. Then, do a LEFT JOIN on empPayrollDetail to achieve the result, using ISNULL(amount, 0) for NULL amounts.
SQL Fiddle
SELECT
epm.EmployeeID,
epm.MasterID,
c.ComponentID,
amount = ISNULL(epd.amount, 0)
FROM empPayrollMaster epm
CROSS JOIN Components c
LEFT JOIN empPayrollDetail epd
ON epd.MasterID = epm.MasterID
AND epd.ComponentID = c.ComponentID

Try this
select empPayrollMaster.EmployeeID,empPayrollMaster.MasterID,
Components.componentid,isnull(empPayrollDetail.amount,0)
from empPayrollMaster
left join Components
on empPayrollMaster.EmployeeID is not null
left join empPayrollDetail
on empPayrollDetail.MasterID = empPayrollMaster.MasterID
and empPayrollDetail.ComponentID = Components.componentid

Try this way
select c.EmployeeID,d.MasterID,c.ComponentID,isnull(d.amount,0) as amount from (
select * from Components a
Cross join empPayrollMaster b) c
left outer join empPayrollDetail d on d.componentid =c.componentid

As you want the component amount for each employee in the master table you should use a insull(payrole_detail.amount,0) or, as #Turophile pointed out, the SQL standard function coalesce(payrole_detail.amount,0) for the amounts column.

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
ORDER BY Customers.CustomerName;

Related

SQL Self Join to work out freight percentage when invoices are stored in the same table

I need to work out the freight percentage value on each shipment the company brings in. The invoices for the freight and the goods are stored in the same table, VSI denotes a goods invoice, VBL denotes a freight invoice, they are joined together via a job cost. I have tried to self join the sets of tables, but the end sum is always multiplied by the amount of matching records. Any help would be appreciated.
Tables
JobCost
JobCostID JobCostDescription JobCostNumber
4910 ITS-1005104 JBC-1004880
4911 ITS-1005105 JBC-1004881
PurchaseInvoice
PIID PINumber ExchangeRate VendorId
1 VSI-1 1 1
2 VSI-2 1 2
3 VBL-1 1 3
PurchaseInvoiceItem
PIItemID PIID Item
1 1 ProductA
2 1 ProductB
3 2 ProductA
4 2 ProductB
5 3 Fuel
6 3 Handling
PurchaseInvoiceItemDetail
PIItemDetailID QtyShipped Cost PIItemID JobCostID
1 2 2500 1 4910
2 2 2500 2 4910
3 2 2500 3 4911
4 2 2500 4 4911
5 1 25 5 4910
6 1 75 6 4910
Vendor
VendorId VendorCode VendorName
1 VEN1 Vendor1
2 VEN2 Vendor2
3 Freight1 Agent1
Desired result
JobCostID JobCostDescription VendorCode VendorName FreightAgentCode FreightAgentName InvoiceTotal FreightTotal FreightPercentage
4910 ITS-1005104 VEN1 Vendor1 Freight1 Agent1 10000 100 1%
4920 ITS-1005105 VEN2 Vendor2 10000
SELECT tblJobCost1.JobCostID, tblJobCost1.JobCostDescription, tblVendor1.VendorCode, tblVendor1.VendorName, tblVendor2.VendorCode AS 'FreightAgentCode', tblVendor2.VendorName AS 'FreightAgentName',
SUM(PurchaseInvoiceItemDetail1.QtyShipped*PurchaseInvoiceItemDetail1.Cost*PurchaseInvoice1.ExchangeRate) AS 'InvoiceTotal',
SUM(PurchaseInvoiceItemDetail2.QtyShipped*PurchaseInvoiceItemDetail2.Cost*PurchaseInvoice2.ExchangeRate) AS 'FreightTotal',
SUM(PurchaseInvoiceItemDetail2.QtyShipped*PurchaseInvoiceItemDetail2.Cost*PurchaseInvoice2.ExchangeRate)/SUM(PurchaseInvoiceItemDetail1.QtyShipped*PurchaseInvoiceItemDetail1.Cost*PurchaseInvoice1.ExchangeRate)*100 AS 'FreightPercentage'
FROM tblJobCost AS tblJobCost1
LEFT JOIN tblJobCost AS tblJobCost2 ON tblJobCost1.JobCostID = tblJobCost2.JobCostID
LEFT JOIN tblPurchaseInvoiceItemDetail AS tblPurchaseInvoiceItemDetail1 ON tblJobCost1.JobCostID = tblPurchaseInvoiceItemDetail1.JobCostID
LEFT JOIN tblPurchaseInvoiceItemDetail AS tblPurchaseInvoiceItemDetail2 ON tblJobCost2.JobCostID = tblPurchaseInvoiceItemDetail2.JobCostID
LEFT JOIN tblPurchaseInvoiceItem AS tblPurchaseInvoiceItem1 ON tblPurchaseInvoiceItem1.PIItemID = tblPurchaseInvoiceItemDetail1.PIItemID
LEFT JOIN tblPurchaseInvoiceItem AS tblPurchaseInvoiceItem2 ON tblPurchaseInvoiceItem2.PIItemID = tblPurchaseInvoiceItemDetail2.PIItemID
LEFT JOIN tblPurchaseInvoice AS tblPurchaseInvoice1 ON tblPurchaseInvoiceItem1.PIID = tblPurchaseInvoice1.PIID
LEFT JOIN tblPurchaseInvoice AS tblPurchaseInvoice2 ON tblPurchaseInvoiceItem2.PIID = tblPurchaseInvoice2.PIID
LEFT JOIN tblVendor AS tblVendor1 ON tblVendor1.VendorId = tblPurchaseInvoice1.VendorID
LEFT JOIN tblVendor AS tblVendor2 ON tblVendor2.VendorId = tblPurchaseInvoice2.VendorID
WHERE tblPurchaseInvoice1.PINumber LIKE 'VSI%' AND tblPurchaseInvoice2.PINumber LIKE 'VBL%'
GROUP BY tblJobCost1.JobCostID, tblJobCost1.JobCostDescription, tblVendor1.VendorCode, tblVendor1.VendorName, tblVendor2.VendorCode, tblVendor2.VendorName
Then you are missing a critical condition:
...
LEFT JOIN tblPurchaseInvoiceItemDetail AS tblPurchaseInvoiceItemDetail2
ON tblJobCost2.JobCostID = tblPurchaseInvoiceItemDetail2.JobCostID
AND tblPurchaseInvoiceItemDetail1.JobCostID = tblPurchaseInvoiceItemDetail2.JobCostID
...

Selecting Same Column Twice Using Alias Table

Below are examples of the tables I am working with. These only represent the columns relevant to my query
_Requirements
RequirementID fkOwningWsID
-------------------------------------------
REQ-RPT-01 1
REQ-RPT-02 2
_Workstream
pk WsNm
-------------------------------------------
1 Workstream1
2 Workstream2
mnWorkstream_Leads
fkWsID fkEeID
-------------------------------------------
1 1
1 2
2 1
2 2
The below table is a result of a union. Employees can be from different companies, the below union lists all the employee IDs, the IDs for the employees who are from Company 1 (0 otherwise) and IDs for employees from company 2 (0 otherwise)
qryTrackerAllEeList
EeID Company1_ID Company2_ID
-------------------------------------------
1 1 0
2 0 2
I am attempting to view the following result
RequirementID WsNm Company1_Lead Company2_Lead
--------------------------------------------------------------------
REQ-RPT-01 Workstream1 1 2
REQ-RPT-02 Workstream2 1 2
I have issued the following SQL
SELECT DISTINCT Req.RequirementID, Ws.Wsnm, company1_id.ee_id, company2_id.ee_id
FROM (((([_Requirements] AS Req
INNER JOIN [_Workstream] AS Ws ON Req.fkOwningWsID = Ws.pkWsID)
INNER JOIN [mnWorkstream_Leads] AS wsLeads ON Ws.pkWsID = wsLeads.fkWsID)
LEFT OUTER JOIN qryTrackerAllEeList AS company1 ON wsLeads.fkEeID = company1.Company1_ID)
LEFT OUTER JOIN qryTrackerAllEeList AS company2 ON wsLeads.fkEeID = company2.Company2_ID)
The issue is, however, that I retrieve the following results
RequirementID WsNm Company1_Lead Company2_Lead
--------------------------------------------------------------------
REQ-RPT-01 Workstream1 2
REQ-RPT-01 Workstream1 1
REQ-RPT-02 Workstream2 2
REQ-RPT-02 Workstream2 1
Any suggestions on how to eliminate these duplicative rows and null values?
Use MAX() and GROUP BY to only select the non null values and group them into one row:
SELECT DISTINCT Req.RequirementID, Ws.Wsnm,
MAX(company1_id.ee_id) as Company1_Lead, MAX(company2_id.ee_id) as Company2_Lead,
FROM (((([_Requirements] AS Req
INNER JOIN [_Workstream] AS Ws ON Req.fkOwningWsID = Ws.pkWsID)
INNER JOIN [mnWorkstream_Leads] AS wsLeads ON Ws.pkWsID = wsLeads.fkWsID)
LEFT OUTER JOIN qryTrackerAllEeList AS company1 ON wsLeads.fkEeID = company1.Company1_ID)
LEFT OUTER JOIN qryTrackerAllEeList AS company2 ON wsLeads.fkEeID = company2.Company2_ID)
GROUP BY req.RequirementID, Ws.Wsnm

SQL Server: Include Missing data in Query

I have two tables in SQL Server that looks as follows,
Table 1:
Store Type
100 A
101 B
102 B
103 B
104 C
105 C
106 A
107 A
108 D
109 D
110 C
111 B
112 D
and table 2:
Store Units
100 5
101 3
102 10
103 6
104 6
105 8
I want to combine the two tables in a query with a relationship link between the Store column of the two tables. The problem i have is that if i create a query between the two then the stores from 106 to 112 does not appear in the table. The query looks as follows,
SELECT dbo.Table1.Store,
dbo.Table1.Type,
dbo.Table2.Units
FROM Table1 INNER JOIN Table2
ON dbo.Table1.Store=dbo.Table2.Store
What should i do to include the stores that does not appear in Table2 (106-112) but in Table1 and make there Units = 0, such that the query table look as follows,
Store Type Units
100 A 5
101 B 3
102 B 10
103 B 6
104 C 6
105 C 8
106 A 0
107 A 0
108 D 0
109 D 0
110 C 0
111 B 0
112 D 0
You want a left outer join instead of an inner join:
SELECT t1.Store, t1.Type, COALESCE(t1.Units, 0) as Units
FROM Table1 t1 LEFT JOIN
Table2 t2
ON t1.Store = t2.Store;
I also introduced table aliases for your query to make it more readable. Note the use of coalesce() so you get 0 for Units instead of NULL.
SELECT dbo.Table1.Store, dbo.Table1.Type, coalesce(dbo.Table2.Units, 0) As Units
FROM Table1
LEFT JOIN Table2 ON dbo.Table1.Store=dbo.Table2.Store

T-SQL recursive query - how to do it?

I have a table with self referencing relation,
ID parentID UserId Title
1 null 100 A
2 1 100 B
3 2 100 C
4 2 100 D
5 null 100 E
6 5 100 F
I want to update UserId from 100 to 101 for all records with ID=1 and its children, so I want to have
ID parentID UserId Title
1 null 101 A
2 1 101 B
3 2 101 C
4 2 101 D
5 null 100 E
6 5 100 F
How can I do it in T-SQL?
You probably want to use a common table expression which allows you to generate recursive queries.
eg:
;with cte as
(
select * from yourtable where id=1
union all
select t.* from cte
inner join yourtable t on cte.id = t.parentid
)
update yourtable
set userid = 101
where id in (select id from cte)

Avoid repeatation of rows for every instance when joined with a table

Hi i have 3 tables and i am trying to join them to get a desire table. I have tried group by and temp tables options to get the desired table but no help. I want to avoid duplicates for every instance of a value in one table from another table.
Table 1 Customer Table:
CstId CstDetails CstType
---------- --------------- ------------
1 address 1 1
2 address 2 1
3 address 3 1
4 address 4 2
5 address 5 2
Table 2 Customer Relationship:
CstId CstGroupId
---------- ----------------
1 4 (this is same as CustomerId)
2 5 (this is same as CustomerId)
3 4 (this is same as CustomerId)
Table 3 Customer Notes:
CstId NotesId NoteTxt
----------- --------- ---------
1 1 note11
1 2 note12
1 3 note13
3 1 note31
4 1 note41
4 2 note42
4 3 note43
4 4 note44
4 5 note45
Now i want the result to be in the below format
Table result:
(NoteId) (Notetxt) (NoteId) (Notetxt)
CstId CstDetails CstGroupId CstNoteId CstNote CstGroupNoteId CstGroupNote
1 address1 4 1 note11 1 note41
1 address1 4 2 note12 2 note42
1 address1 4 3 note13 3 note43
1 address1 4 null null 4 note44
1 address1 4 null null 5 note45
But i am getting CstGroupNote repeated for all the CstNote, which i am trying to avoid.
Is there a way i could achieve this result?
Below is the code i use:
select c.cstid, c.cstdetails, cn.cstnotesid, cn.cstnotetxt
insert into temp1
from customer c
left outer join customernotes cn
on c.cstid = cn.cstid
where c.customertypeid = 1
select cr.cstid, cr.cstgroupid, cn.cstgroupnoteid, cn.cstnotetxt
insert into temp2
from customerrelationship cr
left outer join customernotes cn
on cr.cstgroupid = cn.customerid
select t1.cstid, t1.cstdetails, t1.cstnotesid, t1.cstnotetxt, t2.cstgroupnoteid, t2.cstnotetext
from temp1 t1
left outer join t2
on t1.cstid = t2.cstid
Try:
select CstId,
max(CstDetails) CstDetails,
max(CstGroupId) CstGroupId,
max(CstNoteId) CstNoteId,
max(CstNote) CstNote,
max(CstGroupNoteId) CstGroupNoteId,
max(CstGroupNote) CstGroupNote
from
(select c.CstId,
c.CstDetails,
0 CstGroupId,
n.NotesId CmbNotesId,
n.NotesId CstNoteId,
n.NoteTxt CstNote,
0 CstGroupNoteId,
'' CstGroupNote
from customer c
left outer join customernotes n on c.cstid = n.cstid
where c.customertypeid = 1
union all
select c.CstId,
c.CstDetails,
r.CstGroupId,
n.NotesId CmbNotesId,
0 CstNoteId,
'' CstNote,
n.NotesId CstGroupNoteId,
n.NoteTxt CstGroupNote
from customer c
left outer join customerrelationship r on c.cstid = r.cstid
left outer join customernotes n on r.CstGroupId = n.cstid
where c.customertypeid = 1) u
group by CstId, CmbNotesId
Use a derived table and an outer join
The trick there is the
and cn.cstnotesid = cG.cstnotesid
to link those two on one row
select c.cstid, c.cstdetails, cn.cstnotesid, cn.cstnotetxt
,cG.CstGroupId, cG.cstnotesid, cG.cstnotetxt
from customer c
join customernotes cn
on cn.cstid = c.cstid
outer join (select c.cstid, c.CstGroupId, cn.cstnotesid, cn.cstnotetxt
from customer c
join customernotes cn
on cn.cstid = c.CstGroupId) as cG
on c.cstid = cG.cstid
and cn.cstnotesid = cG.cstnotesid
order by c.cstid, cn.cstnotesid, cG.cstnotesid