I have following tables in mySql.
blog
Field Type
---------- ------------
id int(11)
name varchar(255)
user_id int(11)
share int(14)
user_blog_analytics
Field Type
----------- ------------
id int(11)
blog_id int(11)
ip varchar(255)
impressions int(11)
date date
user_profile
Field Type
----------- ------------
id int(11)
user_id int(11)
description text
share int(14)
user_profile_analytics
Field Type
----------- ------------
id int(11)
user_id int(11)
ip varchar(255)
impressions int(11)
date date
users
Field Type
----------- ------------
id int(11)
email varchar(255)
I want a query that gives me total blog shares of each users from blog table, total profile shares of each users from user_profile table, total blog views from yesterday i.e. from user_blog_analytics table, all time views on profile from user_profile_analytics table.
I created a query but not giving me the results I expect, it only gives me few results.
SELECT a.user_id, COUNT(DISTINCT b.ip) AS blog_view_count, a.share AS blog_share_count, c.share AS profile_share_count, COUNT(DISTINCT d.ip) AS user_profile_view
FROM blog AS a
JOIN user_blog_analytics AS b ON b.blog_id=a.id
JOIN user_profile AS c ON c.user_id=a.user_id
JOIN user_profile_analytics AS d ON d.user_id=c.user_id
JOIN users AS e ON e.id=a.user_id
WHERE DATE_SUB(CURDATE(), INTERVAL 1 DAY) = b.date AND e.role_id=2
GROUP BY a.id;
When I ran this query it gives me only one result but when I manually checked the tables then it should be giving me at least 2 results. Tell me where I am wrong and how can I get the result by modifying this query.
Try this:
SELECT u.id, u.email, b.blog_share_count, b.blog_view_count,
up.profile_share_count, upa.user_profile_view
FROM users u
LEFT JOIN (SELECT b.user_id, SUM(b.share) AS blog_share_count, COUNT(DISTINCT b.ip) AS blog_view_count
FROM blog b
LEFT JOIN user_blog_analytics AS uba ON uba.blog_id = b.id AND DATE_SUB(CURDATE(), INTERVAL 1 DAY) = uba.date
GROUP BY b.user_id
) b ON u.id = b.user_id
LEFT JOIN (SELECT up.user_id, SUM(up.share) AS profile_share_count
FROM user_profile up
GROUP BY up.user_id
) up ON u.id = up.user_id
LEFT JOIN (SELECT up.user_id, COUNT(DISTINCT up.ip) AS user_profile_view
FROM user_profile_analytics up
GROUP BY up.user_id
) upa ON u.id = upa.user_id
Not an answer, but something to think about...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table(i14 INT(14),i4 INT(4));
INSERT INTO my_table VALUES (123456789012345,123456789012345);
SELECT * FROM my_table;
+------------+------------+
| i14 | i4 |
+------------+------------+
| 2147483647 | 2147483647 |
+------------+------------+
So, the numbers in parentheses ain't doing much for ya!
Related
I know there are many questions similar to this one but it seems that nothing fits my problem. I've spent quite a few hours researching this problem and came up with a query that doesn't select the last image, more on that later. So, the problem is a have 3 tables
table: images
| Field | Type
+-------------------+------------------
| id | int(10) unsigned
| filename | varchar(255)
| created_at | timestamp
| updated_at | timestamp
table: offers
| Field | Type
+-------------------+------------------
| id | int(10) unsigned
| message | varchar(255)
| created_at | timestamp
and a table connecting them: offer_images
| Field | Type
+----------+------------------
| offer_id | int(10) unsigned
| image_id | int(10) unsigned
So, the question is:
How do I select all offers with the last updated image (based on updated_at) from the images table that is linked to the offer. Here is what I got so far:
SELECT `o`.*, `i`.`filename`
FROM `offer_images` AS `oi`
INNER JOIN `offers` AS `o` on `oi`.`offer_id` = `o`.`id`
INNER JOIN `images` as `i` on `oi`.`photo_id` = `i`.`id`
GROUP BY `o`.`id`
The query selects everything and it's working besides that it ignores the updated_at field.
Try this:
SELECT o.*, i.*
FROM offers AS o
INNER JOIN (
-- Get the latest update_at date per offer_id
SELECT oi.offer_id, MAX(updated_at) AS max_updated_at
FROM offer_images AS oi
INNER JOIN images AS i ON oi.image_id = i.id
GROUP BY oi.offer_id
) AS d ON o.id = d.offer_id
INNER JOIN offer_images AS oi ON oi.offer_id = d.offer_id
INNER JOIN images AS i ON i.id = oi.image_id AND i.updated_at = d.max_updated_at
The query uses a derived table to get the latest update_at date per offer_id. Using this date we can join back to the images table in order to get the greatest-n-per-group record.
I have three tables in my database first one is account_group, next is ledger and last one is account_receipt,
account_group has fields group_id and group_name, and this group_id is mapped to ledger, ledger table contains fields ledger_name and group_id. and in the last table account_receipt has fields ledger_id and receipt_amount.
so what I need is I want to get receipt details when group_id is given.I cant write the query for this.any help would be appreciated.
schema::
account_group::
id int(11)
group_name varchar(60)
ledger ::
id int(11)
group_id varchar(60)
ledger_name varchar(60)
account_receipt::
id int(11)
ledger_id int(11)
amount float
receipt_date date
Try the following query. It uses JOINs to connect the various tables, column aliases and table aliases.
SELECT
ag.id group_id,
l.id ledger_id,
l.ledger_name ledger_name
ar.id receipt_id,
ar.amount amount,
ar.receipt_date receipt_date
FROM account_receipt ar
INNER JOIN ledger l ON ar.ledger_id = l.id
INNER JOIN account_group ag ON ag.id = l.group_id AND ag.id = <given group id>;
Three table joining example has been given below
select * from Table_A A
join Table_B B on B.id=A.id
join Table_C C on C.id=A.id
I have two tables: customer and mailing :
+==========+ +=============+
| customer | | mailing |
+==========+ +=============+
| id | | id |
+----------+ +-------------+
| name | | customer_id |
+----------+ +-------------+
| mailing_id |
+-------------+
Every time I send a mailing to a customer, I add a row in the mailings table with that mailing id. One mailing can be sent to multiple customers.
I want to have a sql call that returns all customers that have not yet received a certain mailing. How to ?
I am using mysql
select * from customer where id not in (
select customer_id from mailing where mailing_id = #mailing_id
)
Something like
Select c.ID, c.Name
From Customers C
left Join mailing m On c.id = m.customer_id
where m.customer_id is null
SELECT * FROM customers c
JOIN mailings m
ON c.id = m.id
WHERE NOT EXISTS (
SELECT id
FROM mailings i
WHERE i.id = c.id
GROUP BY i.id
)
What you describe is called an ANTI JOIN. Usually there are three different ways for formulating it in SQL: A NOT IN condition with a subquery, a NOT EXISTS condition with a correlated subquery, or a LEFT JOIN with a NOT NULL condition.
So for your query the possibilities are:
SELECT *
FROM customer
WHERE id NOT IN
( SELECT customer_id
FROM mailing)
SELECT *
FROM customer c
WHERE NOT EXISTS
( SELECT customer_id
FROM mailing m
WHERE m.customer_id = c.id)
SELECT *
FROM customer c
LEFT JOIN mailing m ON c.id = m.customer_id
WHERE m.customer_id IS NULL
This blog post compares the different possibilities with MySQL 5.1. According to it, LEFT JOIN / IS NULL and NOT IN are faster than NOT EXISTS.
However, you should try for yourself which one is the fastest. That always depends on your data, indexes, ...
i have 3 tables:
users:
uid int(11) - userid(primary key, auto_increment)
name varchar(255)
pass varchar(64)
created int(11)
projects:
pid int(11) .....
name varchar(150)
description varchar(255)
created int(11)
users_projects:
uid int(11) - user id
pid int(11) - product id
What is the query for: showing the projects(name and description) sorted by name for the user with a certain name?
This is what i've got so far:
SEECT name,description FROM projects ORDER BY name ASC
SELECT a.*, b.*
FROM users a
INNER JOIN users_projects b
ON a.uid = b.uid
INNER JOIN projects c
ON b.pid = c.pid
ORDER BY a.Name ASC
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Looks like you just need to join up the tables. Here #Name is a parameter containing the user's name you want project details for:
SELECT projects.Name,
projects.Description
FROM projects
INNER JOIN users_projects
ON projects.pid = users_projects.pid
INNER JOIN Users
ON users_projects.UId = Users.UId
WHERE Users.Name = #Name
ORDER BY projects.Name ASC
This is my SQL:
"SELECT users.username, users.id_user, friends.name, friends.meet_date
FROM users INNER JOIN friends ON (users.id_user = friends.id_user)
GROUP BY username ORDER BY username";
This is the output on my webpage:
Username Friend's Name Meeting Date
George Nicolas 2010
Man Anatol 2008
For now, it selects just the first rows from database for each user.
Each table has an auto_increment, id_user for the first table and id_friend for the second one.
I would like it to show that friend which were meet last by each user.
I've tried to add an order by "meet_date DESC" but it doesn't work.
How could I achieve my wish?
One standard trick is to use an outer self join:
SELECT users.username, users.id_user, friends.name, friends.meet_date
FROM users
INNER JOIN friends ON (users.id_user = friends.id_user)
LEFT JOIN friends f2 ON friends.meet_date > f2.meet_date
WHERE f2.(primary key) IS NULL
GROUP BY username
ORDER BY username
which finds the date for which there is no other record with a greater date value. This avoids the inefficiencies of correlated subqueries and extra aggregates; or the doubtful assumption that records are always added in meet-date order which is necessary if you want to use the primary key.
* Edited by other user *
You should replace (primary key) by primary key column table or just by a f2 column:
SELECT users.username, users.id_user, friends.name, friends.meet_date
FROM users
left JOIN friends ON (users.id_user = friends.id_user)
LEFT JOIN friends f2 ON friends.meet_date > f2.meet_date
WHERE f2.id_user IS NULL
GROUP BY username
ORDER BY username
Query runs as spected:
| USERNAME | ID_USER | NAME | MEET_DATE |
-------------------------------------------
| a | 1 | c | 0 |
| b | 2 | (null) | (null) |
The easy way is a subquery:
SELECT
users.username,
users.id_user,
( select friends.name
from friends
where (users.id_user = friends.id_user)
ORDER BY friends.meet_date desc
LIMIT 1 ) as friend_name,
( select friends.meet_date
from friends
where (users.id_user = friends.id_user)
ORDER BY friends.meet_date desc
LIMIT 1 ) as friend_meet_date
FROM users
;
* Testing *
create table users (username varchar(50), id_user int);
create table friends ( name varchar(50), id_user int, meet_date int);
insert into users values ( 'a', 1),('b',2);
insert into friends values ('c', 1, 0), ('d',1,1);
Results:
| USERNAME | ID_USER | FRIEND_NAME | FRIEND_MEET_DATE |
-------------------------------------------------------
| a | 1 | d | 1 |
| b | 2 | (null) | (null) |
Try it at sql fiddle.
Notice thant a correlated subquery is not an elegant approach, is the easy approach.
Do you not have an auto_increment field? This would allow you to sort by that. The other option is to change meet_date to a date field so you can properly sort by it. No reason to store a DateTime as a varchar field
Assuming that you have got id as a primary key with auto_increment in users table, this should do the trick:
SELECT MAX(users.id), users.username, users.id_user, friends.name, friends.meet_date
FROM users INNER JOIN friends ON (users.id_user = friends.id_user)
GROUP BY username ORDER BY username
SELECT users.username, users.id_user, friends.name, friends.meet_date
FROM users INNER JOIN friends ON (users.id_user = friends.id_user)
GROUP BY username ORDER BY username
having max(friends.meet_date)=friends.meet_date