SQL Server Left Join Counting - sql

I got this sample code
create table #Reservation
(id int identity(1,1),
name varchar(50)
);
create table #Reservation_details
(id int identity(1,1),
reservation_id int,
reservation_date date,
seated tinyint
);
create table #Payment
(id int identity(1,1),
reservation_id int,
payment decimal(18,2)
);
insert into #Reservation(name)
values ('Spiderman'),('Superman'),('Batman'),('Hulk');
insert into #Reservation_details(reservation_id,reservation_date,seated)
values (1,'2017-12-07',0),(2,'2017-12-08',0),(3,'2017-12-08',1),(4,'2017-12-08',0);
insert into #Payment(reservation_id,payment)
values(1,220),(2,1000)
select
A.id,
A.name,
B.reservation_date,
B.seated,
C.payment
from #Reservation A
inner join #Reservation_details B
on B.reservation_id = A.id
left join #Payment C
on C.reservation_id = B.reservation_id
where reservation_date = '2017-12-08'
drop table #Reservation
drop table #Reservation_details
drop table #Payment
I wanted to get the count of all reservations where date is '2017-12-08' and seated = 1 or payment is not null
I've tried putting where date is '2017-12-08' and seated = 1 or payment is not
null
but instead it showed me the past date also how do use where as count?

Try it
select COUNT(*)
from #Reservation A
inner join #Reservation_details B on B.reservation_id = A.id
left join #Payment C on C.reservation_id = B.reservation_id
where reservation_date = '2017-12-08'
and (B.seated=1 or C.payment is not null)
I think you forgot to use brackets (condition1 OR condition2) for OR operation.
See operator precedence - https://learn.microsoft.com/en-us/sql/t-sql/language-elements/operator-precedence-transact-sql
In your case if you don't use brackets then
reservation_date = '2017-12-08' and B.seated=1 or C.payment is not null
equals the following
(reservation_date = '2017-12-08' and B.seated=1) or C.payment is not null

select
A.id,
A.name,
B.reservation_date,
B.seated,
C.payment
from (#Reservation A
inner join #Reservation_details B
on B.reservation_id = A.id
left join #Payment C
on C.reservation_id = B.reservation_id)
where B.reservation_date = '2017-12-08'
AND (B.seated =1 or C.payment is null)
You can use COUNT function by using HAVING in WHERE clause , it should be last statement and after the GROUP BY clause

Related

SQL- How to update amount(sum) with one time inner join with the multiple row with the same member id

i plan to update the amount with the 3 row with same member id.
This is what i did
DECLARE #UpdatedWagerItem TABLE (MemberID bigint, CompanyID int, amount decimal )
INSERT INTO #UpdatedWagerItem VALUES (3,1,2);
DECLARE #UpdatedWagerItem2 TABLE (MemberID bigint, CompanyID int, amount decimal )
INSERT INTO #UpdatedWagerItem2 VALUES (3,1,5);
INSERT INTO #UpdatedWagerItem2 VALUES (3,1,5);
INSERT INTO #UpdatedWagerItem2 VALUES (3,1,5);
UPDATE m
SET
m.amount = m.amount + u.amount
FROM #UpdatedWagerItem m
INNER JOIN #UpdatedWagerItem2 u
ON m.MemberID = u.MemberID and m.CompanyID = u.CompanyID
SELECT * FROM #UpdatedWagerItem
2nd row and 3rd row does not work. How can i update balance with one shot?
You would need to have a group by function on your 2nd table to sum up the amount first.
UPDATE m
SET
m.amount = m.amount + u.amount
FROM #UpdatedWagerItem m
INNER JOIN (SELECT MemberID,CompanyID,SUM(amount) amount
FROM #UpdatedWagerItem2
GROUP BY MemberID,CompanyID
) u ON m.MemberID = u.MemberID and m.CompanyID = u.CompanyID

Understanding nested select queries

Have a question in regards to what was a select into query that I am changing into an insert into query with a select and I just wanted somebody to help me understand the query and know why the only fields in the select it wants are only certain fields.
Ok so below is a create table statement I have written for the temp tables '#Infants' and '#MobileBookings'.
create table #MobileBookings
(
Reference nvarchar(50),
CreatedDate datetime,
FirstName nvarchar(50),
Surname nvarchar(50),
PersonTypeId int,
PackageId int,
PersonId int,
ProductId int,
StatusId smallint
)
create table #Infants
(
Reference nvarchar(50),
CreatedDate datetime,
FirstName nvarchar(50),
Surname nvarchar(50),
PersonTypeId int,
ProductPersonId int,
StatusId smallint,
FlightNumber nvarchar(50),
DepartureDateTime datetime,
SectorName nvarchar(50),
BoundID varchar(8)
)
Now what I have in the existing code (that I didn't write but trying to manipulate by including insert into instead of what previously was select into to remove certain warnings.
insert into #Infants (
Reference, CreatedDate, FirstName, Surname,
PersonTypeId, ProductPersonId, StatusId, FlightNumber,
DepartureDateTime, SectorName, BoundID
)
select * from
(
select
x.Reference, x.CreatedDate, x.FirstName, x.Surname,
x.PersonTypeId, pp.ProductPersonId, pp.StatusId as 'ProductPersonStatusID', null as 'DependantPPID',
fl.FlightNumber,
fl.DepartureDateTime, fs.SectorName, iif(fr.BoundID=0,'OutBound','InBound') as 'FlightBound'
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservation as fr with (nolock) on fr.ProductId = x.ProductId
inner join Reservations_Live.dbo.Flight as fl with (nolock) on fl.FlightId = fr.FlightId
inner join Reservations_Live.dbo.FlightSector as fs with (nolock) on fs.FlightSectorId = fl.FlightSectorId
INNER join
(
select x.PackageId as 'PKID', frp.DependantProductPersonId as 'DepPPID', frp.ProductPersonID as 'CarerPPID',
pp.StatusId as 'CarerPPST'
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservationPassenger as frp with (nolock) on frp.ProductPersonID = pp.ProductPersonId
where x.PersonTypeId = 1
and pp.StatusId = 3
and frp.DependantProductPersonId is not null
)
as car on car.PKID = x.PackageId and car.DepPPID = pp.ProductPersonId
where x.StatusId < 7
and x.PersonTypeId = 3
and pp.StatusId = 2
and fl.FlightStatusId < 3
and fl.DepartureDateTime > GETUTCDATE()
) as inf;
set #ActualRowCount = ##rowcount;
Ok so in visual studio, if I hover over the * in the select statement, it displays a hover box that shows the only fields it requires to select:
Reference (nvarchar, null),
CreatedDate (datetime, null),
FirstName (nvarchar, null),
Surname (nvarchar, null),
PersonTypeId (int, null),
ProductPersonStatusID(, null),
DependantPPID(void, not null),
FlightBound (, null)
I'm assuming I need to change my create table and insert into to only include these relevant fields above but what I want to know is how come it only wants to select these fields and not include any other relevant fields?
Also in regards to the ProductPersonStatusID and DependantPPID which is based on the 'StatusID', are they actually displayed as two columns in the final output, meaning the create table will need to include both these columns and they both also need to be included in the insert into? StatusId is an int so if this is the case, I'm assuming 'ProductPersonStatusID' should be set as an int but DependantPPID should be set as a null in the CREATE statement?
UPDATE:
Hopefully I'm in the right section but included the subquery for inf as stated in the comment:
update pp
set pp.StatusId = 3
output 'ProductPerson', 'ProductPersonId', inserted.ProductPersonId,
Core.updXMLFragment('StatusId',inserted.StatusId,deleted.StatusId)
into #OutputList
from Reservations_Live.dbo.ProductPerson as pp
inner join #Infants as inf on inf.ProductPersonId = pp.ProductPersonId;
set #UpdateRowCount = ##Rowcount;
Just to make sure, I have changed the create table and the insert into statement to the follow, which I hope is correct:
create table #Infants
(
Reference nvarchar(50),
CreatedDate datetime,
FirstName nvarchar(50),
Surname nvarchar(50),
PersonTypeId int,
ProductPersonStatusID int,
DependantPPID int,
FlightBound varchar(8)
);
--
insert into #Infants (Reference, CreatedDate, FirstName, Surname, PersonTypeId, ProductPersonStatusID, DependantPPID, FlightBound)
select * from...
I suggest you remove the select * altogether. This is bad practice. There is rarely a good reason to use SELECT * As it was you had a couple of fields mismatched.
Note how the order of fields in the INSERT needs to match the order of fields in the SELECT. That's why I like to spread them across a few lines so I can match them up.
Also WITH (NOLOCK) is not magic go fast switch but that's for another post....
insert into #Infants (
Reference, CreatedDate,
FirstName, Surname,
PersonTypeId, ProductPersonId,
StatusId, FlightNumber,
DepartureDateTime, SectorName,
BoundID
)
select
x.Reference, x.CreatedDate,
x.FirstName, x.Surname,
x.PersonTypeId, pp.ProductPersonId,
pp.StatusId as [ProductPersonStatusID], fl.FlightNumber,
fl.DepartureDateTime, fs.SectorName,
iif(fr.BoundID=0,'OutBound','InBound') as [FlightBound]
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservation as fr with (nolock) on fr.ProductId = x.ProductId
inner join Reservations_Live.dbo.Flight as fl with (nolock) on fl.FlightId = fr.FlightId
inner join Reservations_Live.dbo.FlightSector as fs with (nolock) on fs.FlightSectorId = fl.FlightSectorId
INNER join
(
select x.PackageId as 'PKID', frp.DependantProductPersonId as 'DepPPID', frp.ProductPersonID as 'CarerPPID',
pp.StatusId as 'CarerPPST'
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservationPassenger as frp with (nolock) on frp.ProductPersonID = pp.ProductPersonId
where x.PersonTypeId = 1
and pp.StatusId = 3
and frp.DependantProductPersonId is not null
)
as car on car.PKID = x.PackageId and car.DepPPID = pp.ProductPersonId
where x.StatusId < 7
and x.PersonTypeId = 3
and pp.StatusId = 2
and fl.FlightStatusId < 3
and fl.DepartureDateTime > GETUTCDATE()

Selecting Distinct Fields From Joined Rows

I have a table ANIMAL and another table CALF_PARENT
Design of ANIMAL table is:
ID PK IDENTITY(1,1),
TagNo varchar(30)
and other columns...
Design of CALF_PARENT is:
ID PK IDENTITY(1,1),
Parent int (FK from Animal),
IsMother varchar(1)
I am writing following query to join two tables:
SELECT a.[TagNo]
,a.ID
,a2.TagNo
,isnull(cp.Parent,0)
,a3.TagNo
,isnull(cp.Parent,0)
FROM [dbo].[ANIMAL] a
LEFT JOIN [CALF_PARENT] cp
ON a.ID = cp.Calf
LEFT JOIN ANIMAL a2
ON a2.ID = cp.Parent AND cp.IsMother = 'Y' AND a2.ID IS NOT NULL
LEFT JOIN ANIMAL a3
ON a3.ID = cp.Parent AND cp.IsMother = 'N' AND a3.ID IS NOT NULL
Its returning me record like this:
Tag, CalfID, FatherTagNo, FatherID, MotherTagNo, MotherID
FA-56 21 AB-670 3
FA-56 21 CW-59 7
I want it to return me single row like this:
Tag, CalfID, FatherTagNo, FatherID, MotherTagNo, MotherID
FA-56 21 AB-670 3 CW-59 7
What would be the simplest way to implement it.
SELECT DISTINCT a.[TagNo] As Tag
,a.ID As CalfID
,MAX(a2.TagNo) As FatherTagNo
,MAX(isnull(cp.Parent,0)) As FatherID
,MAX(a3.TagNo) As MotherTagNo
,MAX(isnull(cp.Parent,0))As MotherID
FROM [dbo].[ANIMAL] a
LEFT JOIN [CALF_PARENT] cp
ON a.ID = cp.Calf
LEFT JOIN ANIMAL a2
ON a2.ID = cp.Parent AND cp.IsMother = 'Y' AND a2.ID IS NOT NULL
LEFT JOIN ANIMAL a3
ON a3.ID = cp.Parent AND cp.IsMother = 'N' AND a3.ID IS NOT NULL
GROUP BY a.[TagNo] ,a.ID
and with example
declare #t table (id varchar(10),cal int,father varchar(10),fatherid int,mother varchar(20),motherid int)
insert into #t(id,cal,father,fatherid,mother,motherid) values ('FA-56',21,'AB-670',3,NULL,NULL)
insert into #t(id,cal ,father,fatherid,mother,motherid) values ('FA-56',21,null,null, 'CW-59',21)
select distinct id As i,cal,MAX(father),MAX(fatherid),MAX(mother),MAX(motherid) from #t
group by id,cal
try this:
SELECT a.*, cpmd.*, cpfd.*
FROM dbo.ANIMAL a
LEFT JOIN CALF_PARENT cpm ON a.ID = cpm.Calf AND cpm.IsMother = 'Y'
LEFT JOIN ANIMAL cpmd ON cpmd.ID = cpm.Parent
LEFT JOIN CALF_PARENT cpf ON a.ID = cpf.Calf AND cpf.IsMother = 'N'
LEFT JOIN ANIMAL cpfd ON cpfd.ID = cpf.Parent
and your life would be easier if your calf_parent table would consist of 3 columns:
Animal_ID (PK), Father_ID, Mother_ID

Joining Two Temp Tables

I would like to join two temp tables into one big temp table. I want all of the records from my first temp table and want the records from my second temp table ONLY if the ProductID doesn't exist in my first temp table.
First temp table:
--define temporary table
declare #tmp table (
ManagerID int null,
ManagerName varchar(250),
ProductID int null,
ProductName varchar(250),
RFIFixedIncomeAttributionID int null,
Value decimal(8,4) null,
Name varchar(250),
Sector varchar(250)
)
--populate temp table
insert into #tmp
select
m.ManagerID, m.ManagerName, p.ID as 'ProductID', p.ProductName, sa.RFIFixedIncomeAttributionID, sa.Value, sc.Name,
case when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 39 then 'Core'
when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 38 then 'Intermediate'
end as 'Sector'
from Products p
join Managers m on m.ManagerID = p.ManagerID
left join RFIFixedIncomeAttribution fia on fia.ParentID = p.ID and fia.ParentTypeID = 26
left join RFIFixedIncomeSectorAllocation sa on sa.RFIFixedIncomeAttributionID = fia.ID
and sa.RFIFixedIncomeDataTypeID = 1
join RFIFixedIncomeSectorCategories sc on sc.ID = sa.RFIFixedIncomeSectorCategoryID
join SubType1 s1 on s1.SubType1ID = p.SubType1ID
join SubType2 s2 on s2.SubType2ID = p.SubType2ID
join GeographicMandates gm on gm.GeographicMandateID = p.GeographicMandateID
where p.prodclasscategoryid = 4
and fia.year = 2014
and fia.quarter = 6/3
and p.Rank = 1
order by m.ManagerName, p.ProductName
--get filtered dataset
select * from #tmp
where
Sector in ('Core')
Second temp table:
--define temporary table
declare #tmp2 table (
ManagerID int null,
ManagerName varchar(250),
ProductID int null,
ProductName varchar(250),
RFIFixedIncomeAttributionID int null,
Value decimal(8,4) null,
Name varchar(250),
Sector varchar(250)
)
--populate temp table
insert into #tmp2
select
m.ManagerID, m.ManagerName, p.ID as 'ProductID', p.ProductName, sa.RFIFixedIncomeAttributionID, sa.Value, sc.Name,
case when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 39 then 'Core'
when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 38 then 'Intermediate'
end as 'Sector'
from Products p
join Managers m on m.ManagerID = p.ManagerID
join Vehicles v on v.ProductID = p.ID
join ManagerAccounts ma on ma.VehicleID = v.ID
join Accounts a on a.MgrAccountID = ma.MgrAccountID
left join RFIFixedIncomeAttribution fia on fia.ParentID = a.AccountID and fia.ParentTypeID = 6
left join RFIFixedIncomeSectorAllocation sa on sa.RFIFixedIncomeAttributionID = fia.ID
and sa.RFIFixedIncomeDataTypeID = 1
join RFIFixedIncomeSectorCategories sc on sc.ID = sa.RFIFixedIncomeSectorCategoryID
join SubType1 s1 on s1.SubType1ID = p.SubType1ID
join SubType2 s2 on s2.SubType2ID = p.SubType2ID
join GeographicMandates gm on gm.GeographicMandateID = p.GeographicMandateID
where p.prodclasscategoryid = 4
and fia.year = 2014
and fia.quarter = 6/3
and p.Rank = 1
order by m.ManagerName, p.ProductName
--get filtered dataset
select * from #tmp2
where
Sector in ('Core')
Few points that have already brought up
Union is the term you want, join is something quite different.
You are not working with temp tables, you are working with table variables. Not quite the same thing
mysql and mssql are not the same thing, tag your questions as one or the other, not both.
select * from #tmp
union all
select * from #tmp2 where productID not in (select productID from #tmp)
Not sure if I'd rely on this query in MySQL as it'll struggle with the not in clause...you can use the join syntax in Jasmine's answer for the second half of the union clause.
This is a case of "find all rows with NO MATCH in the other table" and we have a pattern for that. First, swap your tables - the table where you expect to be missing rows will be the second or RIGHT table, the other is the LEFT table.
select <columns>
from table1
LEFT OUTER JOIN table1.ID = table2.ID
where table2.ID IS NULL
OR... don't swap the tables and use RIGHT OUTER JOIN - but that's non-standard.
In your code, there's a problem...
and fia.quarter = 6/3
is equivalent to:
and fia.quarter = 2
I think you need some quotation marks there.

Join record with most recent record on second table

I have 2 tables
Delivery
--------
deliveryid int (PK)
description long varchar
DeliveryHistory
---------------
historyid int
delievryid int
statusid int
recordtime timestamp
WHat I am trying to do is a left outer join to bring back all records from table Delivery with only the most recent entry in DeliveryHistory for each delivery. However if there are no entries in the DeliveryHistory for the delivery I would like a null value
I have done this:
select d.deliveryid,d.description, h.statusid from delivery d
left outer join Deliveryhistory h on d.deliveryid = h.deliveryid
where h.recordtime =
( SELECT MAX(recordtime)
FROM Deliveryhistory
WHERE deliveryid = d.deliveryid)
But it only returns the rows that have an entry in DeliveryHistory.
Your where clause is resulting in all null values being excluded. Try
where h.RecordTime is null OR
h.recordtime =
( SELECT MAX(recordtime)
FROM Deliveryhistory
WHERE deliveryid = d.deliveryid)
select d.deliveryid,d.description, h.statusid from delivery d
left outer join Deliveryhistory h on d.deliveryid = h.deliveryid
where (h.recordtime =
( SELECT MAX(recordtime)
FROM Deliveryhistory
WHERE deliveryid = d.deliveryid)
or h.deliveryid = null)
The existing answers are all it takes but if you'd like to do this without using a WHERE clause you can use following construct.
SELECT d.deliveryid
,d.description
, dh.statusid
FROM Delivery d
LEFT OUTER JOIN (
SELECT deliveryid, MAX(recordtime) AS recordtime
FROM DeliveryHistory
GROUP BY
deliveryid
) dhm ON dhm.deliveryid = d.deliveryid
LEFT OUTER JOIN DeliveryHistory dh ON dh.deliveryid = dhm.deliveryid
AND dh.recordtime = dhm.recordtime
CTE to yield the maxrow (IFF the implementation supports CTEs ;-) plus simple left join with the CTE.
WITH last AS (
SELECT * FROM Deliveryhistory dh
WHERE NOT EXISTS (
SELECT *
FROM Deliveryhistory nx
WHERE nx.deliveryid = dh.deliveryid
AND nx.recordtime > dh.recordtime -- no one is bigger: dh must be the max
)
)
SELECT d.deliveryid, d.description, l.statusid
FROM delivery d
LEFT JOIN last l ON d.deliveryid = l.deliveryid
;