Help with a MySQL query - mysql

Given the following two tables:
users (user_id, username, location,
email)
votes (user_id, value, date, ip)
How can I perform a MySQL query to return all the users with total number of votes and sum of votes for each user?
Thank you.

select u.user_id,
(select count(user_id)
from votes v
where v.user_id = u.user_id) as num_votes,
(select sum(value)
from votes v
where v.user_id = u.user_id) as sum_votes
from users u
# if you want: order by ...
EDIT: The subselects are not the most elegant solution, and not really necessary. So here's an outer join version:
select u.user_id, count(v.user_id) as num_votes, sum(v.value) as sum_votes
from users u
left outer join votes v
on u.user_id = v.user_id
group by u.user_id

This works for me:
create table user
(
id int not null auto_increment,
name varchar(80) not null,
location varchar(80) default '',
email varchar(80) default '',
primary key(id)
);
create table vote
(
id int not null auto_increment,
count int not null,
election_date date,
user_id int,
primary key(id),
foreign key(user_id) references user(id)
);
select
user.name, user.email, sum(vote.count)
from user
left join
vote
on user.id = vote.user_id
group by (user_id)

Related

How to count number of orders for each individual user?

I'm new to MySQL and trying to select the total number of orders for each user in the orders table. Also, I'm trying to order the results by most orders to the least orders.
This is what I have for order table
CREATE TABLE `order` (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
created TIMESTAMP NOT NULL DEFAULT NOW(),
user_id INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE RESTRICT
);
And this is what I have for user table
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL,
first_name VARCHAR(255),
last_name VARCHAR(255),
created TIMESTAMP NOT NULL DEFAULT NOW()
);
I have referenced other resources and tried the following, but I'm getting an error..Not sure how I can go about it?
SELECT COUNT(DISTINCT order_id) AS user_id
FROM `order`
GROUP BY user_id
this will
group by user_id
then count all lines
you will get one line per user_id with the count
ps: distinct is useless because order.id is an autoincrement key.
select user_id, count(*) as nb
from order
group by user_id
Or this if you want users with no orders included.
you need to start from user table, join all related orders, and basically do the same counting and grouping as before.
select u.id, count(*) as nb
from user as u
left join `order` as o on o.user_id = u.id
group by u.id

How to get corresponding FIELD to MAX(DATE) in mySQL?

My two tables are as follows :
Table 1 : Transaction
TRANS_ID (primary key), TRANS_DATE, TRANS_STATUS, USER_ID (Foreign_Key)
The same user_id will be repeated when status change
Table 2 : Users
USER_ID (Primary_Key), USER_NAME, USER_DOB, OTHER_INFO
I want to get the user information along with last transaction status.
I am familiar with the following query.
SELECT MAX(Transaction.TRANS_DATE),Transaction.TRANS_STATUS, Users.USER_NAME, Users.USER_DOB
FROM Users
INNER_JOIN Transaction ON Transaction.USER_ID = Users.USER_ID
WHERE Transaction.USER_ID = #UserID
I pass the UserID with Parameter.AddWithValue. Unfortunately, this method does not return the TRANS_STATUS for the MAX(TRANS_DATE). It does return MAX(TRANS_DATE) but TRANS_STATUS is the first occurrence, not the corresponding STATUS to MAX(TRANS_DATE) record.
Please let me know how I could get the TRANS_STATUS for the MAX(TRANS_DATE). I prefer using INNER JOIN but recommendations are appreciated.
I could not still get to working.
Here are my table scripts.
CREATE TABLE `Transactions` (
`TRANS_ID` int(11) NOT NULL,
`TRANS_DATE` datetime NOT NULL,
`TRANS_STATUS` varchar(45) NOT NULL,
`USER_ID` int(11) NOT NULL,
PRIMARY KEY (`TRANS_ID`),
UNIQUE KEY `TRANS_ID_UNIQUE` (`TRANS_ID`),
KEY `USER_ID_idx` (`USER_ID`),
CONSTRAINT `USER_ID` FOREIGN KEY (`USER_ID`) REFERENCES `Users` (`USER_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `Users` (
`USER_ID` int(11) NOT NULL AUTO_INCREMENT,
`USER_NAME` varchar(45) NOT NULL,
`USER_DOB` datetime NOT NULL,
`OTHER_INFO` varchar(45) NOT NULL,
PRIMARY KEY (`USER_ID`),
UNIQUE KEY `USER_ID_UNIQUE` (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
If I understood right this could work for you
SELECT A.USER_ID AS USER_ID, A.TRANS_DATE AS TRANS_DATE, TRANS_STATUS, USER_NAME, USER_DOB
FROM
(SELECT USER_ID, MAX(TRANS_DATE) AS TRANS_DATE FROM TRANSACTION
GROUP BY USER_ID) A
INNER JOIN
(SELECT USER_ID, TRANS_DATE, TRANS_STATUS FROM TRANSACTION) B
ON A.USER_ID = B.USER_ID
AND A.TRANS_DATE=B.TRANS_DATE
INNER JOIN USERS U
ON A.USER_ID=U.USER_ID;
SELECT Users.USER_NAME, Users.USER_DOB
FROM Users usr INNER JOIN(
SELECT Transaction.TRANS_STATUS, MAX(Transaction.TRANS_DATE)
FROM Transaction GROUP BY Transaction.TRANS_STATUS) trs ON trs.USER_ID=usr.USER_ID
You can use LAST_VALUE function
SELECT Top 1
u.User_ID
,u.user_name
,u.user_dob
,u.other_info
,LAST_VALUE(t.Trans_Date) OVER (PARTITION BY t.user_id ORDER BY
t.Trans_Date RANGE BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING) AS Max_Tran_Date
,LAST_VALUE(t.trans_status) OVER (PARTITION BY t.user_id ORDER BY
t.Trans_Date RANGE BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING) as Last_Status
FROM #Users as u
INNER JOIN #Transaction as t ON t.user_id = u.user_id
WHERE u.User_ID = #UserID
You could use a join on the subquery for max TRANS_DATE
select t.max_trans, t.USER_NAME, t.USER_DOB
from Transaction
INNER JOIN
(
SELECT MAX(Transaction.TRANS_DATE) max_trans,
Transaction.USER_ID, Users.USER_NAME, Users.USER_DOB
FROM Users
INNER_JOIN Transaction ON Transaction.USER_ID = Users.USER_ID
WHERE Transaction.USER_ID = #UserID
) t on Transaction.USER_ID = t.USER_ID and t.max_trans = Transaction.TRANS_DATE

How to get distinct pairs for a table?

Tables
CREATE TABLE Users (user_id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL);
CREATE TABLE Ratings (user_id INTEGER NOT NULL,
rating INTEGER NOT NULL,
movie_name varchar(100) NOT NULL,
PRIMARY KEY(user_id, movie_name),
FOREIGN KEY (user_id) REFERENCES Users(user_id));
CREATE TABLE Similarity (user1_id INTEGER NOT NULL,
user2_id INTEGER NOT NULL,
similarity FLOAT,
PRIMARY KEY (user1_id, user2_id),
FOREIGN KEY (user1_id) REFERENCES Users(user_id),
FOREIGN KEY (user2_id) REFERENCES Users(user_id));
Query: Find all distinct user pairs with a Similarityi,j >= 0.7 whose watch list overlaps in at least 12 movies. The result should contain three columns: the user id of the first user and the user id of the second user, and the number of movies they have watched.
My Query: Returns null
SELECT DISTINCT U.user_id, U2.user_id
FROM Users U, Users U2, Ratings R, Similarity S
WHERE U.user_id != U2.user_id AND
R.user_id = U.user_id AND
R.user_id = U2.user_id AND
S.similarity >= 0.7;
I realized U.user_id != U2.user_id AND R.user_id = U.user_id AND R.user_id = U2.user_id makes the table return null. But how do I get distinct user_id pairings?
You need to join the tables
e.g.
FROM User U
JOIN Ratings R ON U.user_id = R.User_id
JOIN Similarity S ON S.user2_id = U.user_id
I would join them first and then use your where clause

SQL JOIN with conditions

I have a conversation table which contains two users ids as foreign keys, and the user table which contains the users details. I want to write a query which returns the conversation table joined to the user table but displaying the name and surname of the user whose id wasn't sent as the parameter.
CREATE TABLE `conversation` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_one_id` int(11) NOT NULL,
`user_two_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`surname` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
)
For example I have
Conversation:
id user_one_id user_two_id
1 1 2
User:
id name surname
1 userone_name userone_surname
2 usertwo_name usertwo_surname
I want a query that will return user_two's name and surname in the join, not user one.
My current query:
SELECT c.id, c.user_one_id, c.user_two_id, u.name, u.surname * FROM conversation c
JOIN user u
WHERE c.user_one_id = 1
OR c.user_two_id = 1
AND IF (c.user_one_id = u.id, c.user_two_id = u.id, c.user_one_id = u.id)
GROUP BY c.id
ORDER BY c.date DESC;
[INNER] JOIN should have an ON clause. (I consider it a flaw that MySQL allows you to omit it.)
The join criteria would have to be: Give me the user of the conversation that is not user 1.
SELECT c.id, c.user_one_id, c.user_two_id, u.name, u.surname
FROM conversation c
JOIN user u ON u.id IN (c.user_one_id, c.user_two_id) AND u.id <> 1
WHERE c.user_one_id = 1 OR c.user_two_id = 1
ORDER BY c.date DESC;

Select 3 tables with count and join

I've 3 tables tb1, users, users_credits.
My gol is to combine two select (sel1, sel2) into a single view and
display 0 in the sel2 where there isn't rows (left join?)
sel1
SELECT
users.userid,
users.datareg,
users_credits.credits,
FROM
users,
users_credits,
WHERE
users.userid = users_credits.userid
Sel2
SELECT COUNT(*) FROM tb1 where tb1.id_user = users.userid
table structure
tb1
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_user` decimal(11,0) NOT NULL,
`datains` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
users
`userid` int(4) unsigned NOT NULL AUTO_INCREMENT,
`datareg` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`userid`)
users_credits
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) NOT NULL,
`credits` decimal(5,0) NOT NULL,
`data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
What is the best way to do this?
Thanks.
SELECT users.userid,
users.datareg,
users_credits.credits,
COALESCE(c.totalCount,0) totalCount
FROM users
LEFT JOIN users_credits
ON users.userid = users_credits.userid
LEFT JOIN
(
SELECT id_user, COUNT(*) totalCount
FROM tb1
GROUP BY id_user
) c ON c.id_user = users.userid
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
UPDATE 1
SELECT users.userid,
users.datareg,
users_credits.credits,
COALESCE(c.totalCount,0) totalCount,
c.max_datains
FROM users
LEFT JOIN users_credits
ON users.userid = users_credits.userid
LEFT JOIN
(
SELECT id_user, MAX(datains) max_datains, COUNT(*) totalCount
FROM tb1
GROUP BY id_user
) c ON c.id_user = users.userid
UPDATE 2
you need to create two views for this:
1st View:
CREATE VIEW tbl1View
AS
SELECT id_user, MAX(datains) max_datains, COUNT(*) totalCount
FROM tb1
GROUP BY id_user
2nd View
CREATE VIEW FullView
AS
SELECT users.userid,
users.datareg,
users_credits.credits,
COALESCE(c.totalCount,0) totalCount,
c.max_datains
FROM users
LEFT JOIN users_credits
ON users.userid = users_credits.userid
LEFT JOIN tbl1View c ON c.id_user = users.userid