Below is the query which works but with some errors:
SELECT dbo.Booking.Cost,
dbo.Booking.StatusID,
dbo.Account.FirstName,
dbo.Attendee.HelmetsPurchased AS ProductsPurchased,
dbo.Attendee.GaragesPurchased,
dbo.Attendee.SecondDriver AS [Driver Name]
FROM dbo.Booking
JOIN dbo.Attendee ON dbo.Booking.EventID = dbo.Attendee.EventID
JOIN dbo.Account ON dbo.Booking.UserID = dbo.Account.UserID
WHERE (dbo.Booking.EventID = 15)
Output:
The issue with the generated table is the column product purchased and driver name is populated with text for every row which in this case it should be populated for only the rows which has Drivername and product purchased. There is only one row in the attendee table which has drivername, product purchase fields populated for username mark, while all the other rows has null value for both the drivername and products.
Instead of an INNER JOIN on the table Attendee you should do a LEFT JOIN. This will include rows where these two columns are null as well.
SELECT b.Cost,
b.StatusID,
ac.FirstName,
at.HelmetsPurchased AS ProductsPurchased,
at.GaragesPurchased,
at.SecondDriver AS [Driver Name]
FROM dbo.Booking b
LEFT JOIN dbo.Attendee at ON b.EventID = at.EventID
LEFT JOIN dbo.Account ac ON b.UserID = ac.UserID
WHERE b.EventID = 15
If you don't need driver name, the following could help:
SELECT
B.EventId,
B.Cost,
B.StatusID,
A.FirstName,
SUM(AT.HelmetsPurchased) AS ProductsPurchased,
SUM(AT.GaragesPurchased) AS GaragesPurchased
FROM
dbo.Booking B
INNER JOIN
dbo.Account A ON B.UserID = A.UserID
LEFT OUTER JOIN
dbo.Attendee AT ON B.EventID = AT.EventID
WHERE (dbo.Booking.EventID = 15)
GROUP BY B.EventId, B.Cost, B.StatusId, A.FirstName
Related
I need to build my query using SQL Server Management Studio Query Designer
I need to display a concatenated string of tbl_B.Name + tbl_C.Name + tbl_D.Name, if Id in tbl_E/tbl_User is equal to UserId in tbl_A
This is the Table structure https://imgur.com/PZagLPq, https://imgur.com/moE4dcf
tbl_A UserId = Id in tbl_E/tbl_User
tbl_B_Id = Id in tbl_B
tbl_C_Id = Id in tbl_C
tbl_D_Id = Id in tbl_D
I tried the below code but doesn't display Name field from tbl_B, tbl_C and tbl_D
SELECT tbl_B.Name AS Expr1, tbl_C.Name AS Expr2, tbl_D.Name AS Expr3, tbl_A.UserId, [tbl_E].Id AS Expr5
FROM tbl_B
INNER JOIN tbl_D ON tbl_B.Id = tbl_D.Id
INNER JOIN tbl_A ON tbl_B.Id = tbl_A.Id
INNER JOIN tbl_C ON tbl_B.tbl_CId = tbl_C.Id AND tbl_D.Id = tbl_C.tbl_DId
INNER JOIN [tbl_E] ON tbl_B.Id = [tbl_E].Id AND tbl_A.UserId = [tbl_E].Id
WHERE (tbl_A.UserId = [tbl_E].Id)
Below query will give you the concatenated string of names for every userId, which has entry in all the tables.
SELECT
"tbl_A"."UserId",
CONCAT("tbl_B"."Name", '-', "tbl_C"."Name", '-', "tbl_D"."Name"),
"tbl_B"."Name" AS Expr1,
"tbl_C"."Name" AS Expr2,
"tbl_D"."Name" AS Expr3
FROM "tbl_E"
INNER JOIN "tbl_A" ON "tbl_A"."UserId" = "tbl_E"."id"
INNER JOIN "tbl_B" ON "tbl_B"."id" = "tbl_A"."tbl_B_id"
INNER JOIN "tbl_C" ON "tbl_C"."id" = "tbl_B"."tbl_C_id"
INNER JOIN "tbl_D" ON "tbl_D"."id" = "tbl_C"."tbl_D_id"
This SQL query needs to be done in ACCESS.
I am trying to do a subquery on the total sales, but I want to link the sale to the province AND to product. The below query will work with one or the other: (po.product_name = allp.all_products) AND (p.province = allp.all_province); -- but it will no take both.
I will be including every month into this query, once I can figure out the subquery on with two criteria.
Select
p.province as [Province],
po.product_name as [Product],
all_price
FROM
(purchase_order po
INNER JOIN person p
on p.person_id = po.person_id)
left join
(
select
po1.product_name AS [all_products],
sum(pp1.price) AS [all_price],
p1.province AS [all_province]
from (purchase_order po1
INNER JOIN product pp1
on po1.product_name = pp1.product_name)
INNER JOIN person p1
on po1.person_id = p1.person_id
group by po1.product_name, pp1.price, p1.province
)
as allp
on (po.product_name = allp.all_products) AND (p.province = allp.all_province);
Make the first select sql into a table by giving it an alias and join table 1 to table 2. I don't have your table structure or data to test it but I think this will lead you down the right path:
select table1.*, table2.*
from
(Select
p.province as [Province],
po.product_name as [Product]
--removed this ,all_price
FROM
(purchase_order po
INNER JOIN person p
on p.person_id = po.person_id) table1
left join
(
select
po1.product_name AS [all_products],
sum(pp1.price) AS [all_price],
p1.province AS [all_province]
from (purchase_order po1
INNER JOIN product pp1
on po1.product_name = pp1.product_name)
INNER JOIN person p1
on po1.person_id = p1.person_id
group by po1.product_name, pp1.price, p1.province --check your group by, I dont think you want pp1.price here if you want to aggregate
) as table2 --changed from allp
on (table1.product = table2.all_products) AND (table1.province = table2.all_province);
I am trying to get a list of our users from our database along with the number of people from the same cohort as them - which in this case is defined as being from the same medical school at the same time.
medical_school_id is stored in the doctor_record table
graduation_dt is stored in the doctor_record table as well.
I have managed to write this query out using a subquery which does a select statement counting the number of others for each row but this takes forever. My logic is telling me that I ought to run a simple GROUP BY query once first and then somehow JOIN the medical_school_id on to that.
The group by query is as follows
select count(ca.id) , cdr.medical_school_id, cdr.graduation_dt
from account ca
LEFT JOIN doctor cd on ca.id = cd.account_id
LEFT JOIN doctor_record cdr on cd.gmc_number = cdr.gmc_number
GROUP BY cdr.medical_school_id, cdr.graduation_dt
The long select query is
select a.id, a.email , dr.medical_school_id,
(select count(ba.id) from account ba
LEFT JOIN doctor bd on ba.id = bd.account_id
LEFT JOIN doctor_record bdr on bd.gmc_number = bdr.gmc_number
WHERE bdr.medical_school_id = dr.medical_school_id AND bdr.graduation_dt = dr.graduation_dt) AS med_count,
from account a
LEFT JOIN doctor d on a.id = d.account_id
LEFT JOIN doctor_record dr on d.gmc_number = dr.gmc_number
If you could push me in the right direction that would be amazing
I think you just want window functions:
select a.id, a.email, dr.medical_school_id, dr.graduation_dt,
count(*) over (partition by dr.medical_school_id, dr.graduation_dt) as cohort_size
from account a left join
doctor d
on a.id = d.account_id left join
doctor_record dr
on d.gmc_number = dr.gmc_number;
Using your same code for group by:
SELECT * FROM (
(
SELECT acc.[id]
, acc.[email]
FROM
account acc
LEFT JOIN
doctor doc
ON
acc.id = doc.account_id
LEFT JOIN
doctor_record doc_rec
ON
doc.gmc_number = doc_rec.gmc_number
) label
LEFT JOIN
(
SELECT count(acco.id)
, doc_reco.medical_school_id
, doc_reco.graduation_dt
FROM
account acco
LEFT JOIN
doctor doct
ON
acco.id = doct.account_id
LEFT JOIN
doctor_record doc_reco
ON
doct.gmc_number = doc_reco.gmc_number
GROUP BY
doc_reco.medical_school_id,
doc_reco.graduation_dt
) count
ON
count.[medical_school_id]=label.[medical_school_id]
AND
count.[graduation_dt]=label.[graduation_date]
)
how about something like this?
select a.doctor_id
, count(*) - 1
from doctor_record a
left join doctor_record b on a.medical_school_id = b.medical_school_id
and a.graduation_dt = b.graduation_dt
group by a.doctor_id
Subtract 1 from the count so that you're not counting the doctor in the "other folks in same cohort" number
I'm defining "same cohort" as "same medical school & graduation date".
I'm unclear on what GMC number is and how it is related. Is it something to do with cohort?
I have a query that selects customers from a table CustomerDetails, and left joins onto another table (CustomerActivity) to get their last login time and finally left joins onto another table (OpenOrderDetails) to get their last open order (if applicable). I also have a big WHERE clause filtering this data
A customer can only have one record in the OpenOrderDetails table at anytime. My query looks like the following:
SELECT CD.*, H.LastCustomerLoginTime, OD.OrderFiledDate, OD.OrderCompletedDate
FROM CustomerDetails CD
LEFT JOIN CustomerActivity H ON H.CustomerID = CD.CustomerID
LEFT JOIN OpenOrderDetails OD ON CD.CustomerID = OD.CustomerID
WHERE CD.OrderStatus IN (1,2,3)
AND (CustomerType = 1 or (CustomerType = 3 and CustomerActive IN (1,2)))
AND (OD.OrderFiledDate IS NULL OR CD.TimeStamp >= OD.OrderFiledDate)
AND (OD.OrderCompletedDate IS NULL OR CD.TimeStamp <= OD.OrderCompletedDate)
My issue is that this query only returns customer records that have a record in the OpenOrderDetails table. How do I return every customer, and OrderFiledDate/OrderCompletedDate if present, and NULL if a record for that customer does not exist in the OpenOrderDetails table?
When doing a LEFT JOIN, referencing ANY of the right side table columns in the WHERE clause will turn it into an INNER JOIN. To get around this, simply remove any and all predicates that reference "right side" columns from the WHERE clause and move them to the LEFT JOIN condition.
Something along these lines...
SELECT
CD.*,
H.LastCustomerLoginTime,
OD.OrderFiledDate,
OD.OrderCompletedDate
FROM
CustomerDetails CD
LEFT JOIN CustomerActivity H
ON H.CustomerID = CD.CustomerID
LEFT JOIN OpenOrderDetails OD
ON CD.CustomerID = DLECS.CustomerID
AND ( OD.OrderFiledDate IS NULL
OR CD.TimeStamp >= OD.OrderFiledDate
)
AND ( OD.OrderCompletedDate IS NULL
OR CD.TimeStamp <= OD.OrderCompletedDate
)
WHERE
CD.OrderStatus IN ( 1, 2, 3 )
AND (
CustomerType = 1
OR
(
CustomerType = 3
AND CustomerActive IN ( 1, 2 )
)
);
Just move some OpenOrderDetails conditions to join clause
SELECT CD.*, H.LastCustomerLoginTime, OD.OrderFiledDate, OD.OrderCompletedDate
FROM CustomerDetails CD
LEFT JOIN CustomerActivity H ON H.CustomerID = CD.CustomerID
LEFT JOIN OpenOrderDetails OD ON CD.CustomerID = DLECS.CustomerID
AND (OD.OrderFiledDate IS NULL OR CD.TimeStamp >= OD.OrderFiledDate)
AND (OD.OrderCompletedDate IS NULL OR CD.TimeStamp <= OD.OrderCompletedDate)
WHERE CD.OrderStatus IN (1,2,3)
AND (CustomerType = 1 or (CustomerType = 3 and CustomerActive IN (1,2)))
I have the follwong Query on multi tables
SELECT DISTINCT b.BoxBarcode as [Box Barcode], (select case when b.ImagesCount IS NULL
then 0
else b.ImagesCount end) as [Total Images], s.StageName as [Current Stage] ,d.DocuementTypeName as [Document Type],
u.UserName as [Start User],uu.UserName as [Finished User]
FROM [dbo].[Operations] o
inner join dbo.LKUP_Stages s on
o.stageid=s.id
inner join dbo.LKUP_Users u on
u.id=o.startuserid
left join dbo.LKUP_Users uu on
uu.id=o.FinishedUserID
inner join boxes b on
b.id=o.boxid
inner join LKUP_DocumentTypes d on
d.ID = b.DocTypeID
where b.IsExportFinished = 0
when i select count from the Boxes table where IsExportFinished = 0
i got the Count 42 records, when i run the above qoury i got 71 records,
i want just the 42 records in Boxes table to retrived.
You are doing a one-to-many join, i.e. at least one of the tables have multiple rows that match the join criteria.
Step one is to find which table(s) that give the "duplicates".
Once you have done that you may be able to fix the problem by adding additional criteria to the join. I'm taking a guess that the same boxid occurs several times in the Operations table. If that is the case you need to decide which Operation row you want to select and then update the SQL accordingly.
Try this one -
SELECT
Box_Barcode = b.BoxBarcode
, Total_Images = ISNULL(b.ImagesCount, 0)
, Current_Stage = s.StageName
, Document_Type = d.DocuementTypeName
, Start_User = u.UserName
, Finished_User = uu.UserName
FROM (
SELECT DISTINCT
o.stageid
, o.boxid
, o.startuserid
, o.FinishedUserID
FROM dbo.[Operations]
) o
JOIN dbo.LKUP_Stages s ON o.stageid = s.id
JOIN dbo.boxes b ON b.id = o.boxid
JOIN dbo.LKUP_DocumentTypes d ON d.id = b.DocTypeID
JOIN dbo.LKUP_Users u ON u.id = o.startuserid
LEFT JOIN dbo.LKUP_Users uu ON uu.id = o.FinishedUserID
WHERE b.IsExportFinished = 0
I guess that if you change your LEFT JOIN into INNER JOIN you will get 42 records as requested.