SQL Server UNION or JOIN - sql-server

I am having a bit of problem with JOIN or UNION? Would you help me solve this?
Here is my story.
I have two tables: tbl_inventory and tbl_delivery.
Here is the scenario. Each week I have to match a delivery and an inventory record. For example: on week 1 I have to show, the delivery and inventory for a specific product.
Inventory Date | Week # |Product |inventory qty | delivery qty
----------------------------------------------------------------------------
2018/02/12 | 7 |cheesecake | 30 | 25 |
It is fine I can do that now. The problem arise when I have no delivery or no inventory for that week? Here is my desired output:
Inventory Date | Week # |Product |inventory qty | delivery qty
----------------------------------------------------------------------------
2018/02/12 | 7 |cheesecake | NULL | 25 |
OR
Inventory Date | Week # |Product |inventory qty | delivery qty
----------------------------------------------------------------------------
2018/02/12 | 7 |cheesecake | 30 | NULL |
Would you help me achieve that? Here is my code
select a.CustCode,
b.Material,
b.Qty as deliveryQty,
d.Qty as inventoryQty
from BigEMerchandiser.dbo.tbl_Delivery_H as a
left join BigEMerchandiser.dbo.tbl_Delivery_D as b
on a.TransCtr = b.TransCtr
left join BigEMerchandiser.dbo.tbl_Inventory_H as c
on datepart(wk, a.DtRcv) = datepart(wk, c.DtRcv)
left join BigEMerchandiser.dbo.tbl_Inventory_D as d
on c.TransCtr = d.TransCtr
left join BigEMasterData.dbo.tbl_Materials as e
on b.Material = e.ExtMatGrp
UNION ALL
select a.CustCode,
b.Material,
d.Qty as deliveryQty,
b.Qty as inventoryQty
from BigEMerchandiser.dbo.tbl_Inventory_H as a
left join BigEMerchandiser.dbo.tbl_Inventory_D as b
on a.TransCtr = b.TransCtr
left join BigEMerchandiser.dbo.tbl_Delivery_H as c
on datepart(wk, a.DtRcv) = datepart(wk, c.DtRcv)
left join BigEMerchandiser.dbo.tbl_Delivery_D as d
on c.TransCtr = d.TransCtr
left join BigEMasterData.dbo.tbl_Materials as e
on b.Material = e.ExtMatGrp
I have switched from using joins and union. But still I get the same result.
Here is my inventory table result:
Here is my delivery table result:
Here is the result of my query:
As we can see, there is only one inventory but it still shows 30 on every delivery. I understand that I have used join that is why. Hope you can help me with understand UNIONs and JOIN here. Hope I explained myself clearly. Thankyou. All you suggestions are appreciated.
EDIT
Here is my new query it s outputting what I want. my problem now is how can I add there where statement? for a specific date range:
select a.CustCode,
b.Material,
b.Qty as deliveryQty,
NULL as inventoryQty
from BigEMerchandiser.dbo.tbl_Delivery_H as a
left join BigEMerchandiser.dbo.tbl_Delivery_D as b
on a.TransCtr = b.TransCtr
left join BigEMasterData.dbo.tbl_Materials as e
on b.Material = e.ExtMatGrp
UNION
select v.CustCode,
b.Material,
NULL as deliveryQty,
b.Qty as inventoryQty
from BigEMerchandiser.dbo.tbl_Inventory_H as v
left join BigEMerchandiser.dbo.tbl_Inventory_D as b
on v.TransCtr = b.TransCtr
left join BigEMasterData.dbo.tbl_Materials as e
on b.Material = e.ExtMatGrp
Thanks a lot!

I suspect the problem is UNION which prevents you from seeing your joins result in duplication. You should use UNION ALL, and correct your joins to include Material.
E.g. something like:
left join BigEMerchandiser.dbo.tbl_Inventory_D as d
on c.TransCtr = d.TransCtr
and c.Material = b.Material
How your tables are connected is not immediately clear, but the point is you are looking for a TransCtr in your inventory. TransCtr = 89 has an inventory of 30, it's just the wrong material.

Related

Select records when 2 column's data will match

I have two tables as shown below:
-----------------------
|EmpNo|Complaint |
-----------------------
|9091 |Change required|
|9092 |No change |
|9093 |Changes done |
-----------------------
Above table contains employee number and his complaints.
I have one another table which contains employee all kind of details as shown below.
-------------------------------
|EmpNo|EmailID |EmpBossNO|
-------------------------------
|9091 |abc#gmail.com|9092 |
|9092 |xyz#gmail.com|9093 |
|9093 |mno#gmail.com|9099 |
-------------------------------
Here, if Empno:9091 will raise any complain then a mail will send to his boss that the complain is raise by your employee and you have to accept it so I want to get EmailID of employee's boss and for that I want one SQL query. I tried the query shown here, but it doesn't work.
select EmpEmailID
from tblComplaint
inner join tblEmpMaster on tblEmpMaster.EmpNo = tblComplaint.EmpPSNo
where tblComplaint.EmpPSNo = tblEmpMaster.EmpBossNo
I want output like.. if complaint is raised by EmpNo:9091 then it will return EmailID of his boss which is xyz#gmail.com.
You are on the right track with a join between the tblComplaint and tblEmpMaster tables. But, you need an additional join to tblEmpMaster to bring in the boss' email for each employee complaint.
SELECT
c.EmpNo,
c.Complaint,
COALESCE(e2.EmailID, 'NA') AS boss_email
FROM tblComplaint c
INNER JOIN tblEmpMaster e1
ON c.EmpNo = e1.empNo
LEFT JOIN tblEmpMaster e2
ON e1.EmpBossNO = e2.EmpNo;
Demo
I used a left self join above, in case a given employee does not have a boss (e.g. for the highest ranking boss). In this case, I display NA for the boss email.
You should self join tblEmpMaster
select boss.EmpEmailID
from tblComplaint
inner join tblEmpMaster emp on emp.EmpNo = tblComplaint.EmpPSNo
inner join tblEmpMaster boss on boss.EmpNo = emp.EmpBossNO
where tblComplaint.EmpPSNo = 9091
DB Fiddle
you can even use sub queries to get the Email_Id of the boss as shown below
SELECT Email_Id
FROM EMP_Details
WHERE Emp_No IN (
SELECT Boss_Id
FROM Emp_Details) AND
Emp_No IN (
SELECT Emp_No
FROM Emp_Complaints)

How to get Result from Select statement rows to columns from multiple views in SQL Server

I have 2 different views:
View #1: Get_MTD_Booking
SELECT
CAST(tbm.booking_datetime AS DATE) AS [Date],
COUNT(tbm.booking_id) AS [TotalShipments],
SUM(tbd.qty) AS [TotalPcs],
SUM(tbd.weight) AS [TotalWeight],
SUM(tbm.amount_wr) AS [Amount],
'Booking' AS [Status],
tbm.source_terminal_id, tbm.source_ccp_id
FROM
tbl_booking_master tbm
INNER JOIN
tbl_booking_detail tbd ON tbm.booking_id = tbd.booking_id
GROUP BY
CAST(tbm.booking_datetime AS DATE),
tbm.source_terminal_id, tbm.source_ccp_id
View #2: Get_MTD_Delivery:
SELECT
CAST(tdm.delivery_datetime AS DATE) AS [Date],
COUNT(tdd.BarCode) AS [TotalShipments],
SUM(tbd.qty) AS [TotalPcs],
SUM(tbd.weight) AS [TotalWeight],
0 AS [Amount],
'Delivery' AS [Mode],
tbm.destination_terminal_id,
tbm.destination_ccp_id
FROM
tbl_delivery_master tdm
INNER JOIN
tbl_delivery_detail tdd ON tdm.delivery_id = tdd.delivery_id
AND tdm.booking_id = tdd.booking_id
INNER JOIN
tbl_booking_master tbm ON tdm.booking_id = tbm.booking_id
INNER JOIN
tbl_booking_detail tbd ON tbm.booking_id = tbd.booking_id
GROUP BY
CAST(tdm.delivery_datetime AS DATE),
tbm.destination_terminal_id, tbm.destination_ccp_id
Each view returns the same number of columns:
1: Date
2: TotalShipments
3: TotalPcs
4: TotalWeight
5: Amount
6: Mode
7: DestinationTerminalId
8: DestinationCCPID
What I actually want is to display all of these results in this format:
|Date | DestinationId | DestinationCCP | TotalShipments_Booked | TotalPcs_Booked | TotalWeight_Booked |TotalShipments_Delivered | TotalPcs_Delivered | TotalWeight_Delivered |
I want the result to be grouped by date and destinationid as well.
I have tried to write a subquery for this, but it didn't helped. Can anyone help me to sort this?
You could just try joining both of your views. There is of course a risk that a given shipment does not match to any actual delivery, in which case there would be a few NULL fields for such a record. But this should work reasonably well under the assumption that every delivery originated at some point with an actual shipment.
SELECT
t1.[DATE],
t1.[TotalShipments] AS TotalShipmentsBooked,
t2.[TotalShipments] AS TotalShipmentsDelivered,
t1.[TotalPcs] AS TotalPcsBooked,
t2.[TotalPcs] AS TotalPcsDelivered,
t1.[TotalWeight] AS TotalWeightBooked,
t2.[TotalWeight] AS TotalWeightDelivered,
t1.[TotalAmount] AS TotalAmountBooked,
t2.[TotalAmount] AS TotalAmountDelivered,
t1.[source_terminal_id] AS TerminalId,
t1.[source_ccp_id] AS CCPID
FROM Get_MTD_Booking t1
LEFT JOIN Get_MTD_Delivery t2
ON t1.[DATE] = t2.[DATE] AND
t1.source_terminal_id = t2.destination_terminal_id AND
t1.source_ccp_id = t2.destination_ccp_id;

SQL query to get data from two rows connected by key

I have a question that seems very simple to me at first but I'm relatively new to SQL and I can't solve it.
I have two tables: 'Applicants' and 'Family Units'.
Applicants:
ApplicantID | FirstName
----------- | ----------
1 | John
2 | Mary
Family Units:
ApplicantID | UnitID| Note
1 | 10 | Member
2 | 10 | Mother
I need to bring in one table Applicant Name and Mother Name.
Mother applicantID should be determined by having same UnitID in Family Units table and Mother Note in the same table (and other details they are not relevant here).
I tried this query:
That obviously doesn't work correct, I get applicant name instead of applicant's mother's name.
Need you help, links to articles and explanations also will be great because I feel that I'm missing something very basic.
; with cte as
(
select fu.*,a.name from
FamilyUnit fu
join applicant a on a.id = fu.id
where type = 'Mother'
)
select a.id,a.name,c.name
from applicant a
join FamilyUnit fu on fu.id = a.id
join cte c on c.unit = fu.unit
where c.id <> a.id
Im not so sure if this is correct: just try it
select * from
(select * from #family_units where note = 'member') as a
left join
(select * from #family_units where note = 'mother') as b
on a.unitid = b.unitid
left join #applicant_table as c
on a.ApplicantID =c.ApplicantID
Test result:
1 10 Member 2 10 Mother 1 John

SELECT DISTINCT showing duplicate dates per customer email

I am trying to retrieve information for the past ten months, but am having a couple of errors. First, my query is getting data from as far back as 2013. Secondly, I am seeing duplicates in my results based on the PolEffDate field, like this:
EntityID | PolEffDate | EMail | CustNo | Producer | BusinessPhone
abcde-12345-fghij-67890 | 2013-09-24 | somewhere#email.com | 31000 | Bob Builder | 123-456-7890
abcde-12345-fghij-67890 | 2013-12-01 | somewhere#email.com | 31000 | Bob Builder | 123-456-7890
abcde-12345-fghij-67890 | 2014-09-24 | somewhere#email.com | 31000 | Bob Builder | 123-456-7890
Here is my SQL Query:
SELECT DISTINCT
CONVERT(VarChar(36), Customer.CustId) AS EntityID
, BasicPolInfo.PolEffDate, Customer.EMail, Customer.CustNo
, (isnull(Employee.Firstname + ' ','') + isnull(Employee.LastName,''))
AS Producer, Employee.BusFullPhone
FROM
Customer INNER JOIN BasicPolInfo ON Customer.CustId = BasicPolInfo.CustId INNER JOIN
Transaction ON BasicPolInfo.PolId = Transaction.PolId INNER JOIN
GeneralBranch ON Customer.GLBrnchCode = GeneralBranch.GLBrnchCode INNER JOIN
GeneralDepartment ON Customer.GLDeptCode = GeneralDepartment.GLDeptCode INNER JOIN
GeneralDivision ON Customer.GLDivCode = GeneralDivision.GLDivCode INNER JOIN
Employee ON BasicPolInfo.ExecCode = Employee.EmpCode
WHERE
BasicPolInfo.PolExpDate >= DATEADD(MONTH, -10,CONVERT(VARCHAR(11),GETDATE(),106))
AND BasicPolInfo.PolExpDate <= CONVERT(VARCHAR(11),GETDATE(),106)
AND Customer.Active = 'Y'
AND Customer.typeCust = 'P'
Thank you for the help. I will try my best to answer any questions.
Daniel, the duplication you are seeing is caused because you have multiple records in BasicPolInfo for each CustID value. You can confirm this by running the following query:
SELECT CustID, COUNT(*)
FROM BasicPolInfo
GROUP BY CustID
HAVING COUNT(*) > 1
Depending on your schema, this may not be an issue - after all, there is probably a perfectly legitimate reason for that! Multiple policies per Customer is my guess.
To resolve the duplication, I would recommend a GROUP BY with MIN() or MAX().
Your other issue, that of retrieving data from earlier dates, is because you are selecting the PolEffDate (presumably, policy effective date), but filtering the PolExpDate (presumably, policy expiration date). Which are you intending to use? Policies that have finished sometime in the last ten months could have started much earlier than that.
To resolve the wider date range, reference the same value in your SELECT and WHERE clauses.
Query below (using MAX() and PolExpDate):
SELECT
CONVERT(VarChar(36), Customer.CustId) AS EntityID,
MAX(BasicPolInfo.PolExpDate) AS PolExpDate, -- note that this is now PolExpDate
Customer.EMail,
Customer.CustNo,
(isnull(Employee.Firstname + ' ','') + isnull(Employee.LastName,'')) AS Producer,
Employee.BusFullPhone
FROM
Customer INNER JOIN
BasicPolInfo ON Customer.CustId = BasicPolInfo.CustId INNER JOIN
[Transaction] ON BasicPolInfo.PolId = [Transaction].PolId INNER JOIN
GeneralBranch ON Customer.GLBrnchCode = GeneralBranch.GLBrnchCode INNER JOIN
GeneralDepartment ON Customer.GLDeptCode = GeneralDepartment.GLDeptCode INNER JOIN
GeneralDivision ON Customer.GLDivCode = GeneralDivision.GLDivCode INNER JOIN
Employee ON BasicPolInfo.ExecCode = Employee.EmpCode
WHERE
BasicPolInfo.PolExpDate >= DATEADD(MONTH, -10,CONVERT(VARCHAR(11),GETDATE(),106))
AND BasicPolInfo.PolExpDate <= CONVERT(VARCHAR(11),GETDATE(),106)
AND Customer.Active = 'Y'
AND Customer.typeCust = 'P'
GROUP BY
CONVERT(VarChar(36), Customer.CustId),
Customer.EMail,
Customer.CustNo,
(isnull(Employee.Firstname + ' ','') + isnull(Employee.LastName,'')),
Employee.BusFullPhone

Find Previous record by date stored in another Table

So i have 2 tables, one keeps the record of the cash on tjhe cash register at the end of the day and how much money is left for the next day, the other keeps a record of basicly the date of the record (tables cannot be joined) All that looks like this:
RegistersTable
------------------
Register_ID| DATE
5 | 02/02/2012
8 | 04/02/2012
1 | 10/02/2012
CashTable
----------------
Register_ID|CashEOD|CashFND
8 |3235 |325
5 |6843 |435
1 |1236 |1953
So what im trying to get is a select statement that should return this
RegisterID| DATE|CashEOD|PrevCashFND
1 |10/02/2012|1236 |325
8 |04/02/2012|3235 |435
5 |02/02/2012|6843 |0/Null
Start with a RegisterID on the CashTable, find the previous RegisterID by the DATE in RegistersTable, get the previous CashFND so the final goal is to know how much was selled on that day.
Cash End of Day minus the Cash left on the register from the previous day should tell me that. Thanks in advance.
Please try the following - I hope it helps:
SELECT
D.RegisterID,
D.[DATE],
CashTable.CashEOD,
CashTable_Prev.CashFND AS PrevCashFND
FROM
(
SELECT
A.RegisterID,
A.[DATE],
B.RegisterID AS PrevID
FROM
RegistersTable A
INNER JOIN RegistersTable B ON A.RegisterID <> B.RegisterID AND A.[DATE] > B.[DATE]
INNER JOIN
(
SELECT
_innA.RegisterID,
_innB.RegisterID As PrevID,
MIN(_innA.[DATE] - _innB.[DATE]) AS MinDateDiff
FROM
RegistersTable _innA
INNER JOIN RegistersTable _innB ON _innA.RegisterID <> _innB.RegisterID AND _innA.[DATE] > _innB.[DATE]
GROUP BY
_innA.RegisterID,
_innB.RegisterID
) C
ON A.RegisterID = C.RegisterID AND B.RegisterID = C.PrevID AND (A.[DATE] - B.[DATE]) = C.MinDateDiff
) AS D
INNER JOIN CashTable
ON CashTable.Register_ID = D.RegisterID
INNER JOIN CashTable AS CashTable_Prev
ON CashTable_Prev.Register_ID = D.PrevID

Resources