Output a record that appears more than x times - sql

I am a beginner in SQL, and I need help to get the solution for this condition.
Output the name of any person who bought tickets to visit the Park more than 4 days in a single month. (Also, output the month.)
create table visitor(
visitID char(n),
name char(n) not null,
primary key (visitID)
);
create table ticket(
ticketID char(n),
ticketType char(n),
day int(n),
month char(n),
year int(n),
visitID char(n),
primary key (ticketID), foreign key (visitID) references visitor
);
I am unable to test my code, but what I have so far is
SELECT name, month
FROM Visitor NATURAL JOIN Ticket AS t
JOIN (SELECT name, month
FROM Visitor NATURAL JOIN Ticket
GROUP BY month, year
HAVING COUNT(1) > 4
) AS s
ON t.name = s.name AND t.month = s.month;
I don't know if this is right or not.
Please help.

SELECT s.name, t.month
FROM Visitor inner JOIN Ticket AS t
ON t.visitID= s.visitID
group by month, year
having count(day)>4

Your query may be right technically. But the subquery answers your question:
SELECT name, month
FROM Visitor NATURAL JOIN Ticket
GROUP BY month, year
HAVING COUNT(1) > 4;
Two points, though. Don't use natural join. It can do strange things, based on the names of columns in the table. Explicitly name the columns, using on or using. And, in some databases, month and year might be reserved words. So they are bad names for columns. You can quote them (in most databases) with double quotes. So:
SELECT "month", "year"
FROM Visitor INNER JOIN
Ticket
using (VisitorId)
GROUP BY "month", "year"
HAVING COUNT(1) > 4;
The query might need to count distinct dates. In this case, the having clause should be:
HAVING count(distinct "day") > 4

I have just started learning Mysql. I am still going through the basic syntax and everything so cant really help. But don't you think there is a fault in your question. As Name attribute in the visitor table is not unique(and it should not even be unique). So basically your not finding the same person. Your just trying to find different person that have the same name that visited the park 4 times in a month.

Related

SQL query to find and display duplicates where one of them have a birth year in 2000s and the other one in 1900s

I am working with table with user ID's but it is not a primary key so it can contain duplicate values and in some cases the birth year is wrong, it is for example 2052 and then user created another account with birth year 1952 which is correct. How to find duplicates so I can eliminate the wrong ones?
I wrote this but it's still not completely what I need
select *
from RF_CUSTOMER a
join ( select OID
from RF_CUSTOMER
group by OID
having count(OID) > 1 ) b
on a.OID= b.OID
order by a.oib;

Use Common Table Expression to get difference between two sets of data

I'm trying to use a common table expression to find the differences between two queries I wrote. The first query returns how many patients belong to each ROOMID(each ID represent a specific room).
Second query I have is how many patients that belong to each ROOMId have surgery operated on them. PatientID represent each patient.
select roomID, count(distinct patientID) as totalinsurgery
from data with (nolock)
where ptprocess = 'surgery'
group by clientid, batchid
Second query:
select CAroomid, sum(patientsinroom) as patientsinroom
from data
group by caroomid
So the idea behind is try to get the 'difference' in result of the two query. So how many patients in the room went to surgery. What is the best way to use common table expression to get the result?
So how many patients in the room went to surgery.
I suspect you just want conditional aggregation:
select roomId,
count(distinct case when ptprocess = 'surgery' then patientID end) as num_surgery
count(distinct patientID) as total
from data
group by roomId;
Note: I have no idea why you are using count(distinct). Can a patient really occur more than one time in a room?

Show only last record with specific field data in access query

My SQL skills are quite basic, but I'm trying to set a database of not-profits for a small business.
I have a table (extract_financial) with financial data:
regno (organisation registration number, unique),
fystart (date, financial year start),
fyend (date, financial year end),
income,
exped (expenditure).
Each organisation will have a few records for different financial years. Not all records include income and expenditure values.
I want to show only one record per organisation (including regno, fyend, income), the latest one which has any income.
I've tried the following script, adapted from a similar question, but it didn't work:
SELECT ef.regno, ef.fyend, ef.income
FROM extract_financial ef
INNER JOIN
(
SELECT regno, Max(fyend) AS MaxOfFyend
FROM extract_financial
GROUP BY regno
) AS efx
ON ef.regno = efx.regno
AND ef.fyend = efx.MaxOfFyend
WHERE ef.income IS NOT NULL
The query to find the latest entry for each [regno] works, but the problem is that the latest record never has any income in it... So I guess I need an IF THEN?
Would appreciate your help, thanks!
You are close. The WHERE clause needs to go in the subquery:
SELECT ef.regno, ef.fyend, ef.income
FROM extract_financial as ef INNER JOIN
(SELECT regno, Max(fyend) AS MaxOfFyend
FROM extract_financial as ef
WHERE ef.income IS NOT NULL
GROUP BY regno
) AS efx
ON ef.regno = efx.regno AND ef.fyend = efx.MaxOfFyend;

Joining section in the From clause

Here,I have used joining section in the from clause ...
select course_id, semester, year, sec_id, avg (tot_cred)
from takes natural join student
where year = 2009
group by course_id, semester, year, sec_id
having count (ID) >= 2
Now, My question is , Is this sql query correct ? If yes then why ? Or If not then why ? Thanks.
Your query is technically correct. However, I would advise you strongly to never using natural join. It is a bug waiting to happen. Why? It uses the names -- and only the names -- of columns in the underlying tables. It does not even use declared foreign key relationships.
Instead, use an explicit on or using clause:
select courseid, semester, year, secid, avg(totcred)
from takes t join
student s
using (studentid)
where year = 2009
group by courseid, semester, year, secid
having count(*) >= 2;
Also:
I assume that the spaces in "course id", "sec id", and "tot cred" are simply typos.
Use table aliases.
Qualify the column names -- that is identify what table they are coming from.

How to produce a distinct count of records that are stored by day by month

I have a table with several "ticket" records in it. Each ticket is stored by day (i.e. 2011-07-30 00:00:00.000) I would like to count the unique records in each month by year I have used the following sql statement
SELECT DISTINCT
YEAR(TICKETDATE) as TICKETYEAR,
MONTH(TICKETDATE) AS TICKETMONTH,
COUNT(DISTINCT TICKETID) AS DAILYTICKETCOUNT
FROM
NAT_JOBLINE
GROUP BY
YEAR(TICKETDATE),
MONTH(TICKETDATE)
ORDER BY
YEAR(TICKETDATE),
MONTH(TICKETDATE)
This does produce a count but it is wrong as it picks up the unique tickets for every day. I just want a unique count by month.
Try combining Year and Month into one field, and grouping on that new field.
You may have to cast them to varchar to ensure that they don't simply get added together. Or.. you could multiple through the year...
SELECT
(YEAR(TICKETDATE) * 100) + MONTH(TICKETDATE),
count(*) AS DAILYTICKETCOUNT
FROM NAT_JOBLINE GROUP BY
(YEAR(TICKETDATE) * 100) + MONTH(TICKETDATE)
Presuming that TICKETID is not a primary or unique key, but does appear multiple times in table NAT_JOBLINE, that query should work. If it is unique (does not occur in more than 1 row per value), you will need to select on a different column, one that uniquely identifies the "entity" that you want to count, if not each occurance/instance/reference of that entity.
(As ever, it is hard to tell without working with the actual data.)
I think you need to remove the first distinct. You already have the group by. If I was the first Distict I would be confused as to what I was supposed to do.
SELECT
YEAR(TICKETDATE) as TICKETYEAR,
MONTH(TICKETDATE) AS TICKETMONTH,
COUNT(DISTINCT TICKETID) AS DAILYTICKETCOUNT
FROM NAT_JOBLINE
GROUP BY YEAR(TICKETDATE), MONTH(TICKETDATE)
ORDER BY YEAR(TICKETDATE), MONTH(TICKETDATE)
From what I understand from your comments to Phillip Kelley's solution:
SELECT TICKETDATE, COUNT(*) AS DAILYTICKETCOUNT
FROM NAT_JOBLINE
GROUP BY TICKETDATE
should do the trick, but I suggest you update your question.