SQL query showing incorrect results - sql

I am using Microsoft Access and I have this SQL query which does all the relevant joins:
SELECT c.ID
FROM ((((((((Cars c
INNER JOIN Offers
ON c.ID = Offers.car_id)
INNER JOIN Users u
ON c.owner_id = u.ID)
INNER JOIN City
ON u.city_id = City.ID)
INNER JOIN Models
ON c.model_id = Models.ID)
INNER JOIN Makes
ON Models.make_id = Makes.ID)
INNER JOIN Type
ON Models.type_id = Type.ID) ))
WHERE ( Offers.decision <> 3 )
In my Cars table I have 1 car and in my offers table I have 3 offers for the same car which have a Offers.decision of 2 and 4, for some reason when I execute the query it shows the same car 3 times like it is going on the basis of 3 offers.
Is their a way to show cars that do not have an Offers.decision of 3?

You should not use a join but a subquery:
SELECT * FROM Cars WHERE ID NOT IN (SELECT DISTINCT car_id FROM Offers WHERE decision <> 3)

Simplify your query to just:
SELECT c.ID
FROM Cars c INNER JOIN
Offers ON c.ID = Offers.car_id
WHERE (Offers.decision <> 3)

Related

retrieve people on same flight

I want to retrieve all people on same flight.
Db Model looks like:
Airplane(airplane_id),airplane_name,modelno)
Passenger (id,firstname,lastname,...)
Booking(booking_id,passenger_id,destination_id,flight_date,....)
Destinations(id,airplane_id,route,distance)
What do i need to correct in this query
SELECT * FROM Passenger as P
left join Booking as B
on P.id = B.passenger_id
left join Destinations as D
on D.id = B.destination_id
left join Airplane as A
on A.airplane_id = D.airplane_id;
How will i use where statement??
Your main issue is that you are joining on all the wrong Ids. See below for what they should be based on your column names. (If this is incorrect I would highly recommend changing your column names so they are less confusing). I have also included a sample where clause, you can put any condition you like in there though.
SELECT P.*
FROM
Passenger AS P
JOIN Booking AS B ON P.Id = B.Passenger_Id
JOIN Destinations AS D ON D.Id = B.Destination_Id
JOIN Airplane AS A ON A.Airplane_Id = D.Airplane_Id
WHERE
D.flight_date = '3/16/2021'
you can execute this query, then add a where clause to filter the results
SELECT *
FROM Airplane a
inner join Booking b on b.airplane_id = a.airplane_id
inner join Passenger p on p.id = b.passenger_id
inner join Destination d on d.id = b.destination_id

Multiple joins with group by (Sum)

When I using multiple JOIN, I hope to get the sum of some column in joined tables.
SELECT
A.*,
SUM(C.purchase_price) AS purcchase_total,
SUM(D.sales_price) AS sales_total,
B.user_name
FROM
PROJECT AS A
LEFT JOIN
USER AS B ON A.user_idx = B.user_idx
LEFT JOIN
PURCHASE AS C ON A.project_idx = C.project_idx
LEFT JOIN
SALES AS D ON A.project_idx = D.project_idx
GROUP BY
????
You need to use subquery as follows:
SELECT A.project_idx,
a.project_name,
A.project_category,
sum(C.purchase_price) AS purcchase_total,
sum(D.sales_price) as sales_total,
B.user_name
FROM PROJECT AS A
LEFT JOIN USER AS B ON A.user_idx = B.user_idx
LEFT JOIN (select project_idx, sum(purchase_price) as purchase_price
from PURCHASE group by project_idx ) AS C ON A.project_idx = C.project_idx
LEFT JOIN (select project_idx, sum(sale_price) as sale_price
from SALES group by project_idx) AS D ON A.project_idx = D.project_idx
I am not sure but you can use inner join of project with user instead of left join.
SELECT A.project_idx,
a.project_name,
A.project_category,
purcchase_total,
sales_total,
B.user_name
FROM PROJECT AS A
LEFT JOIN USER AS B ON A.user_idx = B.user_idx
LEFT JOIN (select project_idx, sum(purchase_price) as purchase_total
from PURCHASE group by project_idx ) AS C ON A.project_idx = C.project_idx
LEFT JOIN (select project_idx, sum(sale_price) as sale_total
from SALES group by project_idx) AS D ON A.project_idx = D.project_idx
This is working correctly on MS-SQL Server.
Thanks to Popeye
You are attempting to aggregate over two unrelated dimensions, and that throws off all the calculations.
Correlated subqueries are an alternative:
SELECT p.*,
(SELECT SUM(pu.purchase_price)
FROM PURCHASE pu
WHERE p.project_idx = pu.project_idx
) as purchase_total,
(SELECT SUM(s.sales_price)
FROM SALES s
WHERE p.project_idx = s.project_idx
) as sales_total,
u.user_name
FROM PROJECT p LEFT JOIN
USER u
ON p.user_idx = u.user_idx ;
Note that this uses meaningful table aliases so the query is easier to read. Arbitrary letters are really no better (and perhaps worse) than using the entire table name.
Correlated subqueries avoid the outer aggregation as well -- and let you select all the columns from the first table, which is what you want. They also often have better performance with the right indexes.

Join query equivalent to Not IN clause (SQL Server 2008)

I have a query with a not in clause like this:
select *
FROM COMPANY c
where c.company_id not In (SELECT SenderId
FROM CrossRef)
and c.id not in (select company_id
FROM USER)
I am wondering if there is a way to re-write that query using a left join in SQL Server 2008.
I tried the following one but it's not giving the correct result
select c.id, c.company_id
from COMPANY c
left join CrossRef cr on c.company_id != cr.senderid, COMPANY c1
left join USER u on c1.id != u.company_id
SELECT *
FROM Company C
LEFT JOIN CrossRef R ON R.SenderID = C.CompanyID
LEFT JOIN [User] U ON U.company_id = C.id
WHERE R.SenderID IS NULL
AND U.company_id IS NULL

SQL - Combining two queries

I have these two Queries I'm trying to combine.
Query 1 - This tells me all the vehicles I have that are in my inventory. Meaning are not in the ownership table:
SELECT VEHICLE.*
FROM VEHICLE
WHERE NOT EXISTS
(SELECT NULL FROM OWNERSHIP WHERE VEHICLE.VEH_ID= OWNERSHIP.VEH_ID);
Query 2 - This one tells me which car is the highest priced for each brand.
SELECT B.BRAND_ID, B.BRAND_NAME, M.MODEL_NAME, C.CLASS_NAME, V.VEH_ID, V.VEH_YEAR, V.VEH_PRICE
FROM (((VEHICLE AS V INNER JOIN CLASS AS C ON V.CLASS_ID = C.CLASS_ID)
INNER JOIN MODEL AS M ON M.MODEL_ID = V.MODEL_ID)
INNER JOIN BRAND AS B ON B.BRAND_ID = M.BRAND_ID)
INNER JOIN (SELECT M.BRAND_ID, MAX(V.VEH_PRICE) AS VEH_PRICE FROM VEHICLE AS V
INNER JOIN MODEL AS M ON M.MODEL_ID = V.MODEL_ID GROUP BY M.BRAND_ID)
AS derived ON (v.VEH_PRICE = derived.VEH_PRICE) AND (b.BRAND_ID = derived.BRAND_ID)
ORDER BY 7 DESC;
I realized that determining which vehicles are the most expensive ones won't matter if they are already owned by a customer. Since the first query tells us which are available, how would I combine these two?
I couldn't test your query, but think this is what you are looking for:
SELECT
B.BRAND_ID,
B.BRAND_NAME,
M.MODEL_NAME,
C.CLASS_NAME,
V.VEH_ID,
V.VEH_YEAR,
V.VEH_PRICE
FROM
(((VEHICLE AS V INNER JOIN CLASS AS C ON V.CLASS_ID = C.CLASS_ID)
INNER JOIN MODEL AS M ON M.MODEL_ID = V.MODEL_ID)
INNER JOIN BRAND AS B ON B.BRAND_ID = M.BRAND_ID)
INNER JOIN (SELECT M.BRAND_ID, MAX(V.VEH_PRICE) AS VEH_PRICE
FROM VEHICLE AS V
INNER JOIN MODEL AS M
ON M.MODEL_ID = V.MODEL_ID
WHERE
NOT EXISTS
(SELECT NULL FROM OWNERSHIP
WHERE V.VEH_ID=OWNERSHIP.VEH_ID)
GROUP BY M.BRAND_ID) AS derived
ON (v.VEH_PRICE = derived.VEH_PRICE)
AND (b.BRAND_ID = derived.BRAND_ID)
WHERE
NOT EXISTS
(SELECT NULL FROM OWNERSHIP
WHERE V.VEH_ID=OWNERSHIP.VEH_ID)
ORDER BY 7 DESC;
You have to exclude cars already owned in the subquery where you calculate the maximum price for each brand, but also in the outer query, to exclude owned cars that have the same price as the maximum of cars that don't have an owner.
Instead of using NOT EXISTS clause, i would also suggest to add one more LEFT JOIN with OWNERSHIP both in the subquery and in the outer query, and to take only the rows where OWNERSHIP.VEH_ID is null.

Query extensibility with WHERE EXISTS with a large table

The following query is designed to find the number of people who went to a hospital, the total number of people who went to a hospital and the divide those two to find a percentage. The table Claims is two million plus rows and does have the correct non-clustered index of patientid, admissiondate, and dischargdate. The query runs quickly enough but I'm interested in how I could make it more usable. I would like to be able to add another code in the line where (hcpcs.hcpcs ='97001') and have the change in percentRehabNotHomeHealth be relfected in another column. Is there possible without writing a big, fat join statement where I join the results of the two queries together? I know that by adding the extra column the math won't look right, but I'm not worried about that at the moment. desired sample output: http://imgur.com/BCLrd
database schema
select h.hospitalname
,count(*) as visitCounts
,hospitalcounts
,round(count(*)/cast(hospitalcounts as float) *100,2) as percentRehabNotHomeHealth
from Patient p
inner join statecounties as sc on sc.countycode = p.countycode
and sc.statecode = p.statecode
inner join hospitals as h on h.npi=p.hospitalnpi
inner join
--this join adds the hospitalCounts column
(
select h.hospitalname, count(*) as hospitalCounts
from hospitals as h
inner join patient as p on p.hospitalnpi=h.npi
where p.statecode='21' and h.statecode='21'
group by h.hospitalname
) as t on t.hospitalname=h.hospitalname
--this where exists clause gives the visitCounts column
where h.stateCode='21' and p.statecode='21'
and exists
(
select distinct p2.patientid
from Patient as p2
inner join Claims as c on c.patientid = p2.patientid
and c.admissiondate = p2.admissiondate
and c.dischargedate = p2.dischargedate
inner join hcpcs on hcpcs.hcpcs=c.hcpcs
inner join hospitals as h on h.npi=p2.hospitalnpi
where (hcpcs.hcpcs ='97001' or hcpcs.hcpcs='9339' or hcpcs.hcpcs='97002')
and p2.patientid=p.patientid
)
and hospitalcounts > 10
group by h.hospitalname, t.hospitalcounts
having count(*)>10
You might look into CTE (Common Table Expressions) to get what you need. It would allow you to get summarized data and join that back to the detail on a common key. As an example I modified your join on the subquery to be a CTE.
;with hospitalCounts as (
select h.hospitalname, count(*) as hospitalCounts
from hospitals as h
inner join patient as p on p.hospitalnpi=h.npi
where p.statecode='21' and h.statecode='21'
group by h.hospitalname
)
select h.hospitalname
,count(*) as visitCounts
,hospitalcounts
,round(count(*)/cast(hospitalcounts as float) *100,2) as percentRehabNotHomeHealth
from Patient p
inner join statecounties as sc on sc.countycode = p.countycode
and sc.statecode = p.statecode
inner join hospitals as h on h.npi=p.hospitalnpi
inner join hospitalCounts on t.hospitalname=h.hospitalname
--this where exists clause gives the visitCounts column
where h.stateCode='21' and p.statecode='21'
and exists
(
select p2.patientid
from Patient as p2
inner join Claims as c on c.patientid = p2.patientid
and c.admissiondate = p2.admissiondate
and c.dischargedate = p2.dischargedate
inner join hcpcs on hcpcs.hcpcs=c.hcpcs
inner join hospitals as h on h.npi=p2.hospitalnpi
where (hcpcs.hcpcs ='97001' or hcpcs.hcpcs='9339' or hcpcs.hcpcs='97002')
and p2.patientid=p.patientid
)
and hospitalcounts > 10
group by h.hospitalname, t.hospitalcounts
having count(*)>10