SQL having and max - sql

My query:
SELECT P.lastname, P.firstname, MAX(MD.movie_id)
FROM Person AS P
INNER JOIN Movie_Directors AS MD ON P.person_id = MD.person_id
INNER JOIN Movie AS M ON M.movie_id = MD.movie_id
GROUP BY P.firstname, P.lastname, MD.movie_id
HAVING MAX(MD.movie_id);
I get this error:
An expression of non-boolean type specified in a context where a condition is expected, near ';'
I need to get a SQL select for the next question, I don't understand the error can anyone help?
The query needs to display the director who has produced the most films so far [firstname, lastname].

You need to provide a logical condition in the HAVING clause, like
HAVING MAX(MD.movie_id) > 100

The ROW_NUMBER clause can help you. Hopefully I don't have any typos in this. Also, if you have a person_id, I recommend you use that instead of the firstname, lastname for the partition.
WITH MaxMovies AS
(
SELECT P.lastname, P.firstname, ROW_NUMBER OVER (PARTITION BY firstname, lastname ORDER BY movie_id DESC) MOVIE_NUMBER
FROM Person AS P
inner join Movie_Directors AS MD ON P.person_id=MD.person_id
inner join Movie AS M ON M.movie_id=MD.movie_id
GROUP BY P.firstname, P.lastname
)
SELECT * FROM MAXMOVIES WHERE MOVIE_NUMBER=1
Reference: https://learn.microsoft.com/en-us/sql/t-sql/functions/row-number-transact-sql?view=sql-server-2017

Related

need help writing subquery

I'm using a health database and trying to display patients who have visited the health facility more than two times. The basic query I have so far is
SELECT FirstName, LastName
FROM PATIENT
I know I have to use a subquery in there somehow, but I don't know if I need to use Count or any other operators to find patients visiting more than two times.
you could use a join with visit and count for distinct(VisitDate) filtering using having for the count > 1
SELECT FirstName, LastName , count(distinct VisitDate)
FROM PATIENT
inner join VISIT on VISIT.patientID = PATIENT.PatientID
group by FirstName, LastName
having count(distinct VisitDate) > 1
use aggregate function count and having clause for comparison
SELECT P.FirstName, P.LastName,COUNT(V.VisitID) as numberOfVisit
FROM VISIT V
JOIN PATIENT P ON P.PatientID = V.PatientID
GROUP BY V.PatientID, P.FirstName, P.LastName
HAVING COUNT(V.VisitID) > 2
By using sub query you can also get same result but no need that 1st query is more appropriate
select * from (
SELECT P.FirstName, P.LastName,COUNT(V.VisitID) as numberOfVisit
FROM VISIT V
JOIN PATIENT P ON P.PatientID = V.PatientID
GROUP BY V.PatientID, P.FirstName, P.LastName
) as T where T.numberOfVisit>2
select x.FirstName,x.LastName from (
SELECT a.FirstName, a.LastName,count(*) n
FROM PATIENTa,visit b
where a.patientid = b.patientid
group by a.FirstName, a.LastName having count(*) > 2
) x

Fetching columns, 4 tables

I’ve ran in to some problems with the following SQL assignment. I’m to retrieve the ID, firstname and lastname of any member who is registered in section that contains the word ‘xyz’.
So far I’ve managed the following:
SELECT m.id, p.firstname, p.lastname FROM member m
INNER JOIN person p ON m.id = p.id
WHERE m.id IN (SELECT id FROM membersection);
How do I go forward from here? I have no idea how to retrieve the sectionid from the membersection table then fetch the section name from the section id using that ID so I can check if the section name contains the previously stated word.
member:
id
member_number
registration_date
membersection:
memberid
sectionid
person:
id
firstname
lastname
section:
id
name
Just keep joining. And in the end use LIKE to check if section.name contains 'xyz'.
SELECT m.id,
p.firstname,
p.lastname
FROM member m
INNER JOIN person p
ON p.id = m.id
INNER JOIN membersection ms
ON ms.memberid = m.id
INNER JOIN section s
ON s.id = ms.sectionid
WHERE s.name LIKE '%xyz%';
There is some ambiguity in your question with regards to how your data are structured; what are the primary and foreign keys?
But, making some assumptions, you're almost there, you can chain multiple join statements together:
select
m.id,
p.firstname,
p.lastname
from
member m
inner join person p on
m.id = p.id
inner join membersection ms on
m.id = ms.memberid
inner join section s on
ms.sectionid = s.id
where
s.name like '%xyz%'
It's not super obvious what's going on with your Data Relationships, but this would be the basic route you might want to take (LEFT JOIN as I do not know the relationship):
SELECT m.id, p.firstname, p.lastname, ms.sectionid
FROM member m
INNER JOIN person p ON m.id = p.id
LEFT JOIN section s ON m.id = s.id
LEFT JOIN membersection ms ON m.id = ms.memberid
WHERE s.name = 'xyz'

SQL Server query to select the highest quantity data row

I have been trying to find a similar case. I found a lot, but I still can't figure it out to adopt to my query.
I have a testDB in SQL Server that has 3 tables, as shown in picture below:
I created query as below:
SELECT P.FirstName,
P.LastName,
O.ProductType,
PO.ProductName,
PO.Quantity
FROM Persons AS P
INNER JOIN Orders AS O ON P.PersonID = O.PersonID
INNER JOIN ProductOrders AS PO ON PO.OrderID = O.OrderID;
Current result, it shows all records from ProductOrders. See picture below:
I want the result that only shows, for each Person name only record with the highest quantity. My expected result as shown in picture below:
Thanks very much for your help.
SQL Server has the TOP WITH TIES/ROW_NUMBER() trick that does this very elegantly:
SELECT TOP (1) WITH TIES P.FirstName, P.LastName, O.ProductType, PO.ProductName, PO.Quantity
FROM Persons P INNER JOIN
Orders O
ON P.PersonID = O.PersonID INNER JOIN
ProductOrders PO
ON PO.OrderID = O.OrderID
ORDER BY ROW_NUMBER() OVER (PARTITION BY P.PersonId, P.ProductType ORDER BY PO.Quantity DESC);
Use Window functions:
SELECT distinct P.FirstName
, P.LastName
, O.ProductType
, first_value(O.ProductName) OVER (Partition By P.FirstName, P.LastName, O.ProductType Order by PO.Quantity desc) as [Productname]
, max(PO.Quantity) OVER (Partition By P.FirstName, P.LastName, O.ProductType) as [Quantity]
FROM Persons AS P
INNER JOIN Orders AS O ON P.PersonID = O.PersonID
INNER JOIN ProductOrders AS PO ON PO.OrderID = O.OrderID;

How to write this query to display a COUNT with other fields

I have following two tables:
Person {PersonId, FirstName, LastName,Age .... }
Photo {PhotoId,PersonId, Size, Path}
Obviously, PersonId in the Photo table is an FK referencing the Person table.
I want to write a query to display all the fields of a Person , along with the number of photos he/she has in the Photo table.
A row of the result will looks like
24|Ryan|Smith|28|6
How to write such query in tsql?
Thanks,
You need a subquery in order to avoid having to repeat all the columns from Person in your group by clause.
SELECT
p.PersonId,
p.FirstName,
p.LastName,
p.Age,
coalesce(ph.PhotoCount, 0) as Photocount
FROM
Person p
LEFT OUTER JOIN
(SELECT PersonId,
COUNT(PhotoId) as PhotoCount
FROM Photo
GROUP BY PersonId) ph
ON p.PersonId = ph.PersonId
SELECT
p.PersonId,
p.FirstName,
p.LastName,
p.Age,
CASE WHEN
t.ThePhotoCount IS NULL THEN 0 ELSE t.ThePhotoCount END AS TheCount
--the above line could also use COALESCE
FROM
Person p
LEFT JOIN
(SELECT
PersonId,
COUNT(*) As ThePhotoCount
FROM
Photo
GROUP BY PersonId) t
ON t.PersonId = p.PersonID
SELECT P.PersonId, FirstName, LastName,Age, COUNT(PhotoId) AS Num
FROM Person P
LEFT OUTER JOIN PHOTO PH ON P.PersonId = PH.PersonId
GROUP BY P.PersonId, FirstName, LastName,Age
select Person.*, count(PhotoId) from Person left join Photo on Person.PersonId = Photo.PersonId
IMO GROUP BY should be the solution, something like this works for me even with other table joins:
SELECT meetings.id, meetings.location, meetings.date, COUNT( users.id ) AS attendees
FROM `meetings`
LEFT JOIN users ON meetings.id = users.meeting_id
WHERE meetings.moderator_id = 'XXX'
GROUP BY meetings.id

Compare subselect value with value in master select

In MS Access, I have a query where I want to use a column in the outer query as a condition in the inner query:
SELECT P.FirstName, P.LastName, Count(A.attendance_date) AS CountOfattendance_date,
First(A.attendance_date) AS FirstOfattendance_date,
(SELECT COUNT (*)
FROM(SELECT DISTINCT attendance_date
FROM tblEventAttendance AS B
WHERE B.event_id=8
AND B.attendance_date >= FirstOfattendance_date)
) AS total
FROM tblPeople AS P INNER JOIN tblEventAttendance AS A ON P.ID = A.people_id
WHERE A.event_id=8
GROUP BY P.FirstName, P.LastName
;
The key point is FirstOfattendance_date - I want the comparison deep in the subselect to use the value in each iteration of the master select. Obviously this doesn't work, it asks me for the value of FirstOfattendance_date when I try to run it.
I'd like to do this without resorting to VB code... any ideas?
How about:
SELECT
p.FirstName,
p.LastName,
Count(a.attendance_date) AS CountOfattendance_date,
First(a.attendance_date) AS FirstOfattendance_date,
c.total
FROM (
tblPeople AS p
INNER JOIN tblEventAttendance AS a ON
a.people_id = p.ID)
INNER JOIN (SELECT people_id, Count (attendance_date) As total
FROM (
SELECT DISTINCT people_id,attendance_date
FROM tblEventAttendance)
Group By people_id) AS c ON
p.ID = c.people_id
GROUP BY
p.ID, c.total;
Can you change
B.attendance_date >= FirstOfattendance_date
to
B.attendance_date >= First(A.attendance_date)