I have three tables activity_log, user, staff. I have to select data from activity_log to identify which user has done which activity.
This is structure of activity_log table
CREATE TABLE `activity_log` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`os` varchar(20) NOT NULL,
`api` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Dumping data for table activity_log
INSERT INTO `activity_log` (`id`, `user_id`, `os`, `api`) VALUES
(1, 1, 'web', 'user/login'),
(2, 2, 'web', 'user/report'),
(3, 1, 'android', 'user/login'),
(4, 2, 'ios', 'user/data'),
(5, 3, 'android', 'user/category'),
(6, 3, 'web', 'user/result'),
(7, 3, 'ios', 'user/send_sms');
This is structure of user table
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Dumping data for table user
INSERT INTO `user` (`id`, `first_name`, `last_name`) VALUES
(1, 'Yogesh', 'Kale'),
(2, 'Sunit', 'Desai'),
(3, 'Paresh', 'Godambe');
This is my staff table
CREATE TABLE `staff` (
`id` int(11) NOT NULL,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Dumping data for table staff
INSERT INTO `staff` (`id`, `first_name`, `last_name`) VALUES
(1, 'abcd', 'asas'),
(2, 'ajay', 'shinde'),
(3, 'kapil', 'parab');
But I have to join activity log on one condition. That condition is based on os column in activity_log table. That condition is if os column contain value as web then I have to join user_id of activity_log with id column of staff table and if os column contain value as ios or android then I have to join user_id of activity_log with id column of user table.
I need two different queries one for getting data with columns id and api from activity_log, first_name, last_name from either staff or user and another for getting total count for same above condition. I have given my table schema for reference.
I have tried following query for getting data
SELECT
al.id as id,
CONCAT(u.first_name, ' ', u.last_name) as user_name,
al.api
FROM
activity_log al
JOIN
user u
ON
u.id = al.user_id
WHERE
al.os IN('android','os')
UNION ALL
SELECT
al.id as id,
CONCAT(st.first_name, ' ', st.last_name) as user_name,
al.api
FROM
activity_log al
JOIN
staff st
ON
st.id = al.user_id
WHERE
al.os = 'web'
This above query returns me right data. But I dont know how to get count with above condition. Thats where I stuck in this. If possible please give me alternate queries for getting data and count.
Please help me in this. I spent whole day to figure out this. Thanks in advance
You can try using UNION ALL to get the required data.
Query 1:
select al.id, al.api,s.first_name, s.last_name from activity_log al inner join staff s on al.user_id=s.id where al.os='web'
UNION ALL
select al.id, al.api,u.first_name, u.last_name from activity_log al inner join user u on al.user_id=u.id where al.os!='web'
Query 2:
select
(select count(*) from activity_log al, staff s where al.user_id=s.id and al.os='web') as webcount,
(select count(*) from activity_log al, user u where al.user_id=u.id and al.os!='web') as othercount
I hope this gives you a direction for your question.
Try with
SELECT ...,count(*) FROM table1
INNER JOIN table2 ON ... WHERE ...
Related
I have three MySQL tables:
For example
A Table is menu ID, name
B table is customer_order ID, order_date
C table is order_item ID, menu_item_id, customer_order_id, order_quantity
I try to output name, sum(order_quantity) in this month
Currently i have two separate query which working ok, but the second query is inside of foreach loop, which seem not so good.
First query which output all the menu items:
$results = $wpdb->get_results( "SELECT * FROM menu WHERE post_id = $pid ORDER BY sort_order ");
Second query will output total of each item sold on each month:
$total = $wpdb->get_col( "SELECT SUM(oi.order_item_quantity)
from order_item as oi
INNER JOIN customer_order as ho ON ho.ID = oi.order_id
WHERE oi.order_item_id = $subC->ID AND YEAR(ho.order_date) = $current_year AND MONTH(ho.order_date) = $current_month ");
I try to merge the two queries into one query, which has taken me whole day but still not able to solve it, can anyone give me some help please.
update
thanks Rene.
Select m.name, m.name as name, sum(oi.order_item_quantity) as sold_monthly from menu as m left join order_item as oi on oi.order_item_id = m.ID left join cusomter_order as co on co.ID = oi.order_id where m.post_id = 110 group by m.ID, m.name
this will output
name sold_monthly
Sushi Lunch Special NULL
Sushi Lunch 19
Sashimi Lunch 61
jason NULL
egg roll NULL
if i add YEAR(co.order_date) = 2016 AND MONTH(co.order_date) = 9
which i only get
name sold_monthly
Sushi Lunch 7
Sashimi Lunch 14
how can i keep sushi lunch special, jason, egg roll, the null item, when i add the YEAR(co.order_date) = 2016 AND MONTH(co.order_date) = 9.
here i try
(year(co.order_date) = 2016 and month(co.order_date) = 10) or sold_monthly is null
which give me a query error
update
thanks Rene again
it's working now
(year(co.order_date) = 2016 and month(co.order_date) = 10) or co.order_date is null
finally solve it, upper have little bug, when i change business_id which may not catch the result i want, so i am add a subquery to it.
Select m.*, p.sold_monthly from menu as m left join ( SELECT SUM(oi.order_item_quantity) as sold_monthly, oi.order_item_id as ID, oi.order_item_name from order_item as oi LEFT JOIN cusomter_order as ho ON ho.ID = oi.order_id WHERE ho.business_id = $pid AND (year(ho.order_date) = $current_year and month(ho.order_date) = $current_month) OR ho.order_date is NULL GROUP by oi.order_item_id )p on p.ID = m.ID where m.post_id = $pid
So you're trying to get a list per post_id limited by the selected month.
The following query will yield that for the following sample data.
SELECT m.ID as ID, m.Name as Name, SUM(oi.order_quantity) as Quantity
FROM menu as m
LEFT JOIN order_item as oi ON oi.menu_item_id = m.ID
LEFT JOIN customer_order as co ON co.ID = oi.customer_order_id
WHERE m.post_id = 0 AND YEAR(co.order_date) = 2016 AND MONTH(co.order_date) = 9 OR co.order_date is NULL
GROUP BY m.ID,m.Name,m.sort_order
ORDER BY m.sort_order
Sample Data
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
DROP TABLE IF EXISTS `customer_order`;
CREATE TABLE `customer_order` (
`ID` int(11) NOT NULL,
`order_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_german2_ci;
TRUNCATE TABLE `customer_order`;
INSERT INTO `customer_order` (`ID`, `order_date`) VALUES
(1, '2016-09-06 00:00:00'),
(2, '2016-09-13 00:00:00'),
(3, '2016-08-09 00:00:00'),
(4, '2016-09-19 00:00:00');
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu` (
`ID` int(11) NOT NULL,
`sort_order` int(11) NOT NULL,
`post_id` int(11) NOT NULL,
`Name` varchar(20) COLLATE utf8_german2_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_german2_ci;
TRUNCATE TABLE `menu`;
INSERT INTO `menu` (`ID`, `sort_order`, `post_id`, `Name`) VALUES
(2, 0, 0, 'Test 1'),
(4, 1, 0, 'Test 2'),
(5, 2, 0, 'Test 3');
DROP TABLE IF EXISTS `order_item`;
CREATE TABLE `order_item` (
`ID` int(11) NOT NULL,
`menu_item_id` int(11) NOT NULL,
`customer_order_id` int(11) NOT NULL,
`order_quantity` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_german2_ci;
TRUNCATE TABLE `order_item`;
INSERT INTO `order_item` (`ID`, `menu_item_id`, `customer_order_id`, `order_quantity`) VALUES
(1, 2, 1, 1),
(2, 2, 2, 3),
(3, 4, 1, 1),
(4, 4, 2, 4),
(5, 2, 3, 3),
(6, 4, 3, 1),
(7, 2, 4, 4);
ALTER TABLE `customer_order`
ADD PRIMARY KEY (`ID`);
ALTER TABLE `menu`
ADD PRIMARY KEY (`ID`),
ADD KEY `idx_pid` (`post_id`);
ALTER TABLE `order_item`
ADD PRIMARY KEY (`ID`),
ADD KEY `idx_coid` (`customer_order_id`),
ADD KEY `idx_miid` (`menu_item_id`);
ALTER TABLE `customer_order`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
ALTER TABLE `menu`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
ALTER TABLE `order_item`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
ALTER TABLE `order_item`
ADD CONSTRAINT `CostomerOrderConstrain` FOREIGN KEY (`customer_order_id`) REFERENCES `customer_order` (`ID`),
ADD CONSTRAINT `MenuItemConstrain` FOREIGN KEY (`menu_item_id`) REFERENCES `menu` (`ID`);
Good luck integrating the query, let me know if it worked.
Update: Updated sample data to reproduce the actual problem. Updated the Solution Query.
I have 3 tables, but data is only fetch from 2 tables.
I'm trying to get the lowest bids for selected items and display user name with the lowest bid.
Currently query works until when we display user name, it shows wrong user name, which does not match the bid.
Below is working example of structure and query.
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE `bid` (
`id` int(11) NOT NULL,
`amount` float NOT NULL,
`user_id` int(11) NOT NULL,
`item_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
INSERT INTO `bid` (`id`, `amount`, `user_id`, `item_id`) VALUES
(1, 9, 1, 1),
(2, 5, 2, 1),
(3, 4, 3, 1),
(4, 3, 4, 1),
(5, 4, 2, 2),
(6, 22, 5, 1);
-- --------------------------------------------------------
CREATE TABLE `item` (
`id` int(11) NOT NULL,
`name` varchar(100) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
INSERT INTO `item` (`id`, `name`) VALUES
(1, 'chair'),
(2, 'sofa'),
(3, 'table'),
(4, 'box');
-- --------------------------------------------------------
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`name` varchar(100) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
INSERT INTO `user` (`id`, `name`) VALUES
(1, 'James'),
(2, 'Don'),
(3, 'Hipes'),
(4, 'Sam'),
(5, 'Zakam');
ALTER TABLE `bid`
ADD PRIMARY KEY (`id`);
ALTER TABLE `item`
ADD PRIMARY KEY (`id`);
ALTER TABLE `user`
ADD PRIMARY KEY (`id`);
ALTER TABLE `bid`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=7;
ALTER TABLE `item`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;
ALTER TABLE `user`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;
Query 1:
SELECT b.id, b.item_id, MIN(b.amount) as amount, b.user_id, p.name
FROM bid b
LEFT JOIN user p ON p.id = b.user_id
WHERE b.item_id in (1, 2)
GROUP BY b.item_id
ORDER BY b.amount, b.item_id
Results:
| id | item_id | amount | user_id | name |
|----|---------|--------|---------|-------|
| 5 | 2 | 4 | 2 | Don |
| 1 | 1 | 3 | 1 | James |
Explanation of query:
Get the selected items (1, 2).
get the lowest bid for thous items - MIN(b.amount)
display user names, who has given the bid - LEFT JOIN user p on p.id = b.user_id (this is not working or I'm doing something wrong)
[Note] I can't use sub-query, I'm doing this in doctrine2 (php code) which limits mysql sub-query
No, you are not necessarily fetching the user_id who has given the bid. You group by item_id, so you get one result row per item. So you are aggregating and for every column you say what value you want to see for that item. E.g.:
MIN(b.amount) - the minimum amount of the item's records
MAX(b.amount) - the maximum amount of the item's records
AVG(b.amount) - the avarage amount of the item's records
b.amount - one of the amounts of the item's records arbitrarily chosen (as there are many amounts and you don't specify which you want to see, the DBMS simply choses one of them)
This said, b.user_id isn't necessarily the user who made the lowest bid, but just one random user of the users who made a bid.
Instead find the minimum bids and join again with your bid table to access the realted records:
select bid.id, bid.item_id, bid.amount, user.id as user_id, user.name
from bid
join
(
select item_id, min(amount) as amount
from bid
group by item_id
) as min_bid on min_bid.item_id = bid.item_id and min_bid.amount = bid.amount
join user on user.id = bid.user_id
order by bid.amount, bid.item_id;
You can solve this using a subquery. I am not 100% sure if this is the most efficient way, but at least it works.
SELECT b1.id, b1.item_id, b1.amount, b1.user_id, p.name
FROM bid b1
LEFT JOIN user p ON p.id = b1.user_id
WHERE b1.id = (
SELECT b2.id
FROM bid b2
WHERE b2.item_id IN (1, 2)
ORDER BY b2.amount LIMIT 1
)
This first selects for the lowest bid with for item 1 or 2 and then uses the id of that bid to find the information you need.
Edit
You are saying that Doctrine does not support subqueries. I have not used Doctrine a lot, but something like this should work:
$subQueryBuilder = $entityManager->createQueryBuilder();
$subQuery = $subQueryBuilder
->select('b2.id')
->from('bid', 'b2')
->where('b2.item_id IN (:items)')
->orderBy('b2.amount')
->setMaxResults(1)
->getDql();
$queryBuilder = $entityManager->createQueryBuilder();
$query = $queryBuilder
->select('b1.id', 'b1.item_id', 'b1.amount', 'b1.user_id', 'p.name')
->from('bid', 'b1')
->leftJoin('user', 'p', 'with', 'p.id = b1.user_id')
->where('b1.id = (' . $subQuery . ')')
->setParameter('items', [1, 2])
->getQuery()->getSingleResult();
Currently at the moment I have managed to join two tables to retrieve the information that is need.
I have now decided to try and retrieve another piece of information from a another table ( users.user_id ) but the query I'm trying to use doesn't seem to work. If someone could help with the query would be great.
Here is my current query that works fine.
"SELECT films.movie_title, films.rating, films.actor, reviewed.review
FROM films
INNER JOIN reviewed
ON films.movie_id=reviewed.movie_id";
Here is the query being used to get data from three tables but wont work
"SELECT films.movie_title, films.rating, films.actor, reviewed.review users.name
FROM films
OUTER JOIN reviewed, users
ON films.movie_id=reviewed.movie_id && films.user_id=users.user_id";
Database: film
Table structure for table films
CREATE TABLE IF NOT EXISTS `films` (
`movie_id` int(4) NOT NULL AUTO_INCREMENT,
`movie_title` varchar(100) NOT NULL,
`actor` varchar(100) NOT NULL,
`rating` varchar(20) NOT NULL,
`user_id` int(100) NOT NULL,
PRIMARY KEY (`movie_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `films` (`movie_id`, `movie_title`, `actor`, `rating`, `user_id`) VALUES
(1, 'batman', 'christian bale', 'Excellent', 3),
(2, 'Bne', 'reee', 'Ok', 3),
(3, 'Today', 'dd', 'Fair', 3);
Table structure for table reviewed
CREATE TABLE IF NOT EXISTS `reviewed` (
`review_id` int(4) NOT NULL AUTO_INCREMENT,
`review` mediumtext NOT NULL,
`movie_id` int(4) NOT NULL,
PRIMARY KEY (`review_id`),
KEY `movie_id` (`movie_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `reviewed` (`review_id`, `review`, `movie_id`) VALUES
(1, 'Wicked film', 1),
(2, 'gedtg', 2),
(3, 'dddd', 3);
Table structure for table users
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(4) NOT NULL AUTO_INCREMENT,
`email` varchar(40) NOT NULL,
`password` varchar(40) NOT NULL,
`name` varchar(30) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=30 ;
INSERT INTO `users` (`user_id`, `email`, `password`, `name`) VALUES
(1, 'ben#talktalk.net', 'password', 'Ben'),
(2, 'richard#talk.net', '1', 'richard'),
Try this:
SELECT films.movie_title, films.rating, films.actor, reviewed.review, users.name
FROM films
LEFT JOIN reviewed ON films.movie_id=reviewed.movie_id
LEFT JOIN users ON films.user_id=users.user_id
Is it possible that you want to have the user_id in your reviews table?
That way you'd have the following:
table of movies; only one per movie
table of users; only one per user
table of reviews; one per review linked to a user and to a movie
The reviews table would now have the rating, the review itself, a user id, a movie id and a unique review id.
That way a Batman could be given an Excellent rating by me and an Average rating by you without duplicating the movie row.
To just fix your above query, you can use the following:
SELECT films.movie_title, films.rating, films.actor, reviewed.review, users.name FROM films, reviewed, users WHERE films.movie_id = reviewed.movie_id AND films.user_id = users.user_id;
If you want to print only films with reviews, you don't need OUTER JOIN.
SELECT films.movie_title, films.rating, films.actor, reviewed.review users.name
FROM films JOIN reviewed on films.movie_id=reviewed.movie_id
JOIN users ON films.user_id=users.user_id;
If you want to print all films, even those with 0 reviews, you have to use LEFT JOIN (MySQL doesn't have FULL OUTER JOIN).
SELECT films.movie_title, films.rating, films.actor, reviewed.review users.name
FROM films LEFT JOIN reviewed on films.movie_id=reviewed.movie_id
LEFT JOIN users ON films.user_id=users.user_id;
I have the following sample database set up -
CREATE TABLE IF NOT EXISTS `companies`(
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`company` varchar(75) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `companies` (`id`, `company`) VALUES
(1, 'Acme Widget Company'),
(2, 'Intrepid Inc.'),
(3, 'Allied Corp.');
CREATE TABLE IF NOT EXISTS `companies_customers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`company_id` int(11) NOT NULL,
`customer_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `companies_customers` (`id`, `company_id`, `customer_id`) VALUES
(1, 2, 1),
(2, 2, 2),
(3, 2, 4),
(4, 1, 3),
(5, 1, 1);
CREATE TABLE IF NOT EXISTS `customers` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`firstname` varchar(25) NOT NULL,
`lastname` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `customers` (`id`, `firstname`, `lastname`) VALUES
(1, 'John', 'Smith'),
(2, 'Sue', 'Jones'),
(3, 'David', 'Flanders'),
(4, 'Kathy', 'Freeman');
CREATE TABLE IF NOT EXISTS `orders` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`customer_id` int(11) NOT NULL,
`amount` decimal(10,0) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `orders` (`id`, `customer_id`, `amount`) VALUES
(1, 1, 500),
(2, 3, 1000),
(3, 1, 250),
(4, 4, 800),
(5, 4, 100);
I need to write a query which retrieves a list of all company names, a count of the number of customers in each company, and a sum of the customers orders in each company, like this -
Company Total Customers All Orders Total
Acme Widget Company 2 750
Intrepid Inc. 3 1650
Allied Corp. 0 0
I nearly have it resolved with the following SQL -
SELECT company AS 'Company', customersCount AS 'Total Customers', customerOrdersTotal AS 'All Orders Total'
FROM
( SELECT cc.customer_id, SUM(innerQuery.ordersTotal) customerOrdersTotal
FROM (SELECT cu.id customerId, SUM(amount) ordersTotal
FROM customers cu
JOIN orders o ON o.customer_id = cu.id
GROUP BY customerId
) innerQuery
JOIN companies_customers cc ON innerQuery.customerId = cc.customer_id
GROUP BY cc.customer_id
) inner_1
RIGHT JOIN
( SELECT cc.id, c.company, COUNT(*) customersCount
FROM companies c
JOIN companies_customers cc ON c.id = cc.company_id
GROUP BY c.id
) inner_2
ON inner_1.customer_id = inner_2.id
It does not print out the company (Allied) without a customer or total. So close, I just need a nudge in the right direction. Thanks.
Since the orders are linked to the companies via the customers, I don't think you need to perform two separate subqueries and join them; rather, I think you can just write:
SELECT companies.company AS "Company",
IFNULL(COUNT(DISTINCT companies_customers.customer_id), 0) AS "Total Customers",
IFNULL(SUM(orders.amount), 0) AS "All Orders Total"
FROM companies
LEFT
JOIN companies_customers
ON companies_customers.company_id = companies.id
LEFT
JOIN orders
ON orders.customer_id = companies_customers.customer_id
GROUP
BY companies.id
;
Edited to add: That said, I have to say that the schema doesn't really make sense to me. You have a many-to-many relationship between customers and companies — so, for example, John Smith is a customer of Acme Widget Company and of Intrepid Inc. — but then orders are just a property of the customer, not of the company. This means that if an order belongs to John Smith, then it necessarily belongs both to Acme Widget Company and to Intrepid Inc.. I don't think that can be right. Instead of having a customer_id field, I think orders needs to have a companies_customers_id field.
I have 3 table that to keep team,tournament_round AND score_team_member about competition TEAM_A Vs TEAM_B ,multiple of round.(1,2,3...n) and multiple of members of team there is score by oneself.This code above are useful very much.
SELECT team.name AS "TEAM",team.id,
IFNULL(COUNT(DISTINCT `tournament_round`.id), 0) AS "TotalWin",
IFNULL(SUM(`score_team_member`.`score`)/(select count(*) from `team_member`where team_id=team.id group by team_id ), 0) AS "ScoreofTeam"
FROM `team`
LEFT
JOIN `tournament_round`
ON `tournament_round`.team_winner_id = `team`.id
LEFT
JOIN `score_team_member`
ON `score_team_member`.team_id = `team`.id
WHERE `team`.thematch_id='6' AND `team`.`category1`='MEP'
GROUP BY `team`.id ORDER by `TotalWin`DESC ,`ScoreofTeam` DESC
Sample out put click here JPG
Table Designer JPG
I have the following MySQL structure (minimized a lot):
CREATE TABLE `site_movies` (
`id` int(10),
`title` varchar(90),
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
INSERT INTO `site_movies` VALUES(1, 'Borrowers, The');
INSERT INTO `site_movies` VALUES(2, 'Louis C.K.: Chewed Up');
INSERT INTO `site_movies` VALUES(3, 'Louis C.K.: Shameless');
INSERT INTO `site_movies` VALUES(4, 'Vinni-Pukh');
CREATE TABLE `site_movies_directors` (
`id` mediumint(8),
`name` varchar(255),
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
CREATE TABLE `site_movies_directors_connections` (
`movie_id` mediumint(8),
`director_id` mediumint(8)
) ENGINE=MyISAM;
CREATE TABLE `site_movies_seen` (
`object_id` int(10),
`date` varchar(10),
`rating` tinyint(2)
) ENGINE=MyISAM;
INSERT INTO `site_movies_seen` VALUES(1, '0', 4);
INSERT INTO `site_movies_seen` VALUES(2, '1293821757', 5);
INSERT INTO `site_movies_seen` VALUES(3, '1293821758', 7);
INSERT INTO `site_movies_seen` VALUES(4, '0', 6);
And then the following query (also minimized a lot):
SELECT m.title, s.date
FROM site_movies_seen s
INNER JOIN site_movies m ON s.object_id = m.id
LEFT JOIN site_movies_directors_connections AS mdc ON ( m.id = mdc.movie_id )
GROUP BY mdc.movie_id, s.date
ORDER BY s.date ASC
Prints:
title date
Borrowers, The 0
Louis C.K.: Chewed Up 1293821757
Louis C.K.: Shameless 1293821758
Notice that "Vinni-Pukh" is missing because it is the second entry in the _seen table with date = 0. How can I include all entires, even when several entires have the same timestamp?
Change your group by statement to this:
GROUP BY m.id, s.date
Your join condition says m.id = mdc.movie_id, so you might think that these two fields are always equal and therefore it doesn't matter whether you write m.id or mdc.movie_id in your GROUP BY. This is not true because you are using a LEFT JOIN, not an INNER JOIN. This means that mdc.movie_id can be NULL, and all NULL entries go into the same group.
Also, since you aren't selecting any columns from the site_movies_directors_connections you should omit it from the query completely.
SELECT m.title, s.date
FROM site_movies_seen s
INNER JOIN site_movies m ON s.object_id = m.id
GROUP BY m.id, s.date
ORDER BY s.date