Use multiple tables to find a record MySQL - php

I'm sorry if the title is missleading, but I didn't know how to sum it up, sorry :(
Basically, I've made a event system that shows events that you can attend.
I got two tables
"events" and "registrations"
The events table contains all information about a single event, datetime of the event, price,, etc...
Everytime a user clicks register on an event, a record is added to the registration table.
A record looks like this: Registrationid, eventid, date, status and userid
Now I use this query to get all passed events:
SELECT * FROM events WHERE Date < CURRENT_DATE() ORDER BY Date ASC
I only want it to show previous events on the user page, if the user has actually attended the event. Is there a way I can check the registration table, and if a record exists for that event; show the event? I can do this is php, but I figured it would be possible via MySQL, though I'm not completely sure.
Is there a query that can handle the job? :)

Sure, that's a pretty simple join operation. Here's how I would do this:
select e.*
from event e join registration r
on (r.event_id=e.event_id)
where r.user_id=123 and e.date < current_date()
order by e.date asc
A couple of other tips:
Avoid using reserved words and data types as column names (e.g. "date")
The default storage engine in MySQL does not support referential integrity. If you need referential integrity, take a peek at InnoDB.
For more on joins in MySQL, check this out: https://dev.mysql.com/doc/refman/5.0/en/join.html

SELECT * FROM events e , registrations r where e.eventid = r.eventid AND e.Date < CURRENT_DATE()

SELECT e.*
FROM events e
JOIN registrations r
ON e.eventid = r.eventid
WHERE Date < CURRENT_DATE()
AND r.userid = <insert id here>
ORDER BY Date ASC
This query would give you all the fields from the events table, where a record in the registrations table has a specific user id.

Example Select with a join with your information:
SELECT * FROM events AS e WHERE e.Date < CURRENT_DATE() JOIN registration AS r ON e.id = r.eventid ORDER BY e.Date ASC

Despite other commenters' suggestion to use a JOIN (which is a decent suggestion), I think it's actually better in this case to use IN plus a subquery:
SELECT *
FROM events
WHERE eventid IN
( SELECT r.eventid
FROM registrations r
WHERE r.userid = ...
)
AND date < CURRENT_DATE()
ORDER
BY date ASC
(replacing the ... with the appropriate user-ID).

Using a JOIN, you can select the registrations rows for the userid, and then get the events data
SELECT
r.*, // Instead of *, you could specify the columns - r.userid, r.status, etc
e.* // Instead of *, you could specify the columns - e.event_name, e.Date, etc
FROM
registrations r
JOIN
events e
ON
r.eventid = e.id
WHERE
r.userid = YOUR_USERID
AND
r.status = ATTENDED
AND
e.Date < CURRENT_DATE()
ORDER BY
e.Date ASC

Related

query group by with order by

i need to create query with group by and order by, and i dont know how to do it.
query should return one record for the newest date for existing device_serial_number. enter image description here
so i would to get id 591 nad 592
solution can be in sql or the best way it will be in symfony, through query builder etc.
There are many ways to accomplish what you want.
First Way
The oldest way to select first, best, worst, whatever within a group is with a correlated subquery:
Select * from mytable outer
Where created_at = (
Select max(created_at)
from mytable inner
Where inner.device_serial_number = outer.device_serial_number
)
Second Way
Use a subselect to find earliest dates for all devices, them join back to the original table to filter:
Select a.*
From mytable a Inner Join
(Select device_serial_number, max(created_at) as latedate
From mytable b
Group By device_serial_number
) b
On a.device_serial_number=b.device_serial_number
And a.created_at=b.latedate
Third way
Use a window function to rank order all the dates and then pick the number one ranking.
Select * From (
Select *
, rank() Over (Partition By device_serial_number Order by created_at desc) as myrank
From mytable
)
Where myrank=1
Notice that while these 3 solutions use different aspects of SQL, they all have a common analytical approach. They are all two step processes whose first (inner) part involves finding the most recent created_at date for each device_serial_number and then reapplying that result back to the original table in the second (outer) part.

MySQL query exclude entry depending on date

I need help with a MySQL query. I have 2 tables, clients and payments. The table clients has 2 fields id and name. The table payments has id, id_clients, pay_month. The clients need to pay every month a certain amount.
I want to search only the name of clients which has not paid the current month.
my query
SELECT name FROM clients WHERE id NOT IN (SELECT DISTINCT id_client FROM payments WHERE pay_month > '2014-03-15' ORDER BY pay_month DESC)
I managed to resolve my query.
I used php to store the date $today = date("Y-m-d");
SELECT DISTINCT clients.id, clients.name FROM clients WHERE clients.id NOT IN (SELECT DISTINCT id_clients FROM payments WHERE pay_month > '".$today."' ORDER BY pay_month DESC) ORDER BY clients.name ASC
Thank you everyone for your help.
Maybe something like this.
SELECT
c.name as client_name,
p.pay_month as payment_month
FROM clients c
LEFT JOIN payments p on p.id_clients = c.id
WHERE p.id IS NULL AND YEAR(p.pay_month) >= YEAR(NOW()) AND MONTH(p.pay_month) > MONTH(NOW());
if you could give us some sample data i can build a sql fiddle and do it much easier.
just edited to fix the date format/check

Retrieving row count and returning 0 when no rows

I've written a query to retrieve how many website signups I've had every day:
SELECT created, COUNT(id)
FROM signups
GROUP BY created
ORDER BY created desc
However, this only retrieves rows for days where people have actually signed up. If nobody has signed up in a day, I would like to return 0 for that day. Is there a way to do this using SQL or will I have to parse through the results using PHP?
Assuming created to be of type date for lack of information.
Postgres provides the wonderful generate_series() to make this easy:
SELECT d.created, COUNT(s.id) AS ct
FROM (
SELECT generate_series(min(created)
, max(created), interval '1 day')::date AS created
FROM signups
) d
LEFT JOIN signups s USING (created)
GROUP BY 1
ORDER BY 1 DESC;
This retrieves minimum and maximum day from your table automatically and provides one row per day in between.
You can use NULLIF function:
SELECT created, NULLIF(COUNT(id), 0)
FROM signups
GROUP BY created
ORDER BY created desc
Documentation: http://www.postgresql.org/docs/8.1/static/functions-conditional.html
You need to make use of a calendar table that has a series of dates and join with it
select cal.created,coalesce(total) as total from calender_table as cal left join
(
SELECT created, COUNT(id) as total
FROM signups
GROUP BY created
) as source on cal.created=source.created
ORDER BY cal.created desc
You should create a calendar table in your database (or generate it in a query) and join it with yours then you will get 0 for empty days
SELECT calendar.c_date, COUNT(signups.id)
FROM calendar
left join signups on calendar.c_date=signups.created
GROUP BY c_date
ORDER BY c_date desc
Here is a way to make a calendar date in PostgreSQL

Need to check which row has most likes between two tables

I'm fairly new to MYSQL!
I need to make a SQL query where i check how many likes a row has (between two tables)
I found another question that looked like mine, but i can't get it to return anything (even though it doesn't create an error.
query:
SELECT *
FROM likes
INNER JOIN (SELECT likes.like_id,
COUNT(*) AS likes
FROM likes
INNER JOIN uploads ON likes.upload_id=uploads.upload_id
WHERE uploads.upload_date >= DATE_SUB(CURDATE(), INTERVAL 8 DAY)
GROUP BY uploads.upload_id) x ON x.like_id = likes.like_id
ORDER BY x.likes DESC
Link to the original question:
MySQL, Need to select rows that has the most frequent values in another table
Help is much appreciated
Kind regards,
Mathias
Since you didn't post your table structure I'll have to guess..
select someid, count(*) cnt from
(
select * from table1 t1 join table2 t2 on t1.someid = t2.someid
) as q0 group by someid order by cnt desc;
It will need tweaking to fit your schema.

MySQL, Need to select rows that has the most frequent values in another table

I'm kind of new to SQL and I can't find the solution to my problem. I have two tables. In table A, I'm storing a lot of comments, each with a unique ID.
In table B, I'm storing every vote (like=1 and dislike=0) for every comment with a datetime. There will be an entry for every vote, so there will be tons of rows for each comment in table A.
I need to retrieve all the comments and sort them such that the weekly most liked comments are at the top, but I'm not sure how.
Here's what I have so far, but not sure how to continue:
SELECT * FROM comment INNER JOIN logs ON comment.c_id=logs.c_id WHERE logs.daterate >= DATE_SUB(CURDATE(), INTERVAL 8 DAY) AND logs.rated=1
To clarify, I need to get all entries from logs with rated = 1 in the past week and sort them by the most frequent c_id in descending order, and get distinct c_id for each row... if that makes sense
Please ask questions if I didn't make it clear enough, thanks!!
SELECT *
FROM comment
INNER JOIN (SELECT comment.c_id,
COUNT(*) AS cnt
FROM comment
INNER JOIN logs ON comment.c_id=logs.c_id
WHERE logs.daterate >= DATE_SUB(CURDATE(), INTERVAL 8 DAY)
AND logs.rated=1
GROUP BY comment.c_id) x ON x.c_id = comment.c_id
ORDER BY x.cnt DESC
Try this -
I have first queried all records from logs table which are rated 1 and are from 7 days from current date and also are ordered based on the count of c_id. Then joined this with the COmments table.
SELECT Comment.* FROM comment C
INNER JOIN (SELECT logs.c_id as c_id,count(logs.c_id) as logcount FROM logs
WHERE logs.rated=1
AND logs.daterate BETWEEN GETDATE() AND DATEADD(day,-7,getdate())
Group by logs.c_id
order by count(logs.c_id) desc) X
ON C.c_id = X.c_id
ORDER BY X.logcount DESC

Categories