I would like know how to build a query based another query result.
for example:
I have this table named groups:
group_id | user_id | is_admin
146 | 1 | 1
146 | 3 | 1
146 | 6 | 1
146 | 7 | 1
102 | 21 | 1
105 | 174 | 1
109 | 369 | 1
So, I execute this query to get all groups based on user_id
SELECT * FROM groups WHERE user_id = 6;
The result is?
group_id | user_id | is_admin
146 | 6 | 1
But, I would like to get now, all groups based on group_id. So, I would like
execute this query:
SELECT * FROM groups where group_id = 146;
So, I have this query result:
group_id | user_id | is_admin
146 | 1 | 1
146 | 3 | 1
146 | 6 | 1
146 | 7 | 1
In resume, I would like find which group or user belongs and select all rows that contain their group_id
1 - SELECT * FROM groups WHERE user_id = 6;
2 - SELECT * FROM groups WHERE groups in (146,102, ...);
NOTE: The user_id can belong to more than one group.
Thank you.
Use = and a subquery if you only expect one group per user (as in your sample data):
select g.*
from groups g
where g.group_id = (select g2.group_id from groups g2 where g2.user_id = 6);
Use in if a user could be in multiple groups:
select g.*
from groups g
where g.group_id in (select g2.group_id from groups g2 where g2.user_id = 6);
Related
I know that the question title may not be quit clear to understand but I try to explain:
users_table:
id | name | admin | property_id
-----------------------------------
1 | x | 1 | 0
2 | y | 1 | 0
3 | z | 0 | 1
5 | t | 0 | 2
6 | u | 0 | 2
7 | o | 0 | 2
users_table has two or more records which are admin and some other records which belong to one of these admin records by matching the property_id with the id. In the end what I want is the admin row data and the count of its properties. This is what should be the output from the first part of the query:
id | name | admin | property_count
-----------------------------------
1 | x | 1 | 1
2 | y | 1 | 3
Until now I know how to get the desired results but here begins the problem.I have another table
sells_table:
id | seller_id | sell_amount
----------------------------
1 | 3 | 250
2 | 5 | 120
3 | 7 | 100
4 | 5 | 200
So this is the logic: every admin has many properties and each property has many sells.
I want all records for each admin from the users_table plus the count of its property_id.
And then query the sells_table in a way where for each property of each admin the number of sells and the sum of the total sells gets calculated.
for example this should be the result for the admin with the id 2 and the name y:
name | properties | property_sells | property_amount
--------------------------------------------------------
y | 3 | 3 | 420
y has 3 properties. Property with id 5 which belongs to y(admin) has two sells and id 7 which also belongs to y(admin) has one sell and the sum of these 3 sells is 420.
I think this is what you want:
select ua.id, ua.name, ua.admin, count(distinct u.id) as property_count,
sum(s.sell_amount) as amount
from users_table ua left join
users_table u
on ua.id = u.property_id left join
sales s
on s.seller_id = u.id
where ua.admin = 1
group by ua.id, ua.name, ua.admin;
http://sqlfiddle.com/#!9/36834d/2
SELECT u.id, U.name, u.admin, COUNT(DISTINCT ut.id) property_count, SUM(st.sell_amount)
FROM users_table u
LEFT JOIN users_table ut
ON u.id = ut.property_id
LEFT JOIN sells_table st
ON ut.id = st.seller_id
WHERE u.admin = 1
GROUP BY u.id, u.admin, u.name
I have a SQL table user_game which contains the games that a user owns:
| id | user_id | game_id |
|----|---------|---------|
| 83 | 1 | 1 |
| 84 | 1 | 2 |
| 85 | 1 | 3 |
| 86 | 2 | 2 |
| 87 | 2 | 3 |
| 88 | 2 | 4 |
| 89 | 3 | 2 |
I am trying to count the number of users which have 1 game, 2 games, 3 games.. etc.
User 1 has 3 games, User 2 has 3 games, and User 3 has 1 game. Therefore these are the results I want to achieve:
| no_of_games | COUNT(no_of_games) |
|-------------|--------------------|
| 1 | 1 |
| 2 | 0 |
| 3 | 2 |
COUNT(no_of_games) is the number of users that have that number of games.
I can individually get the number of users for each no_of_games with this query:
-- Select no. of users with 1 game
SELECT no_of_games, COUNT(no_of_games)
FROM
(
-- Select no. of games each user has
SELECT user_id, COUNT(1) as no_of_games
FROM user_game
GROUP BY user_id
) as A
WHERE no_of_games = 1;
which gives the results:
| no_of_games | COUNT(no_of_games) |
|-------------|--------------------|
| 1 | 1 |
However I have to change the no_of_games = 1 to 2, 3, 4... manually and UNION them with this solution and I can't do it for ~60 cases.
Is there a simpler way to achieve this?
Your problem is a bit tricky, because groups of games which do not appear in your data with a certain frequency (e.g. 2) will not appear in the result set just using your original table. In the query below, I use a second table called nums which simply contains the sequence 1 through 10 representing counts of number of games. By using a LEFT JOIN we can retain each game count in the final result set.
SELECT t1.no_of_games,
COALESCE(t2.no_of_games_count, 0) AS no_of_games_count
FROM nums t1
LEFT JOIN
(
SELECT t.no_of_games, COUNT(*) AS no_of_games_count
FROM
(
SELECT COUNT(*) AS no_of_games
FROM user_game
GROUP BY user_id
) t
GROUP BY t.no_of_games
) t2
ON t1.no_of_games = t2.no_of_games
ORDER BY t1.no_of_games
And here is the definition I used for nums:
CREATE TABLE nums (`no_of_games` int);
INSERT INTO nums (`no_of_games`)
VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
Demo here:
SQLFiddle
You can find count of games for each user and then find count of users for each count of games.
select cnt no_of_games, count(*) cnt_no_of_games
from(
select user_id, count(*) cnt
from your_table
group by user_id
) t group by cnt;
I have a points table, where important columns are:
id userid orderid
1 10 150
2 10 150
3 15 151
4 12 152
5 11 152
I need to find all orderid which have multiple/various userid. The result would be:
id userid orderid
4 12 152
5 11 152
I can do it in PHP, but I hope someone have time to help me with mysql query. What I have tried so far is probably irrelevant.
Use COUNT(DISTINCT) and HAVING to find orderid with multiple various userid.
SqlFiddleDemo
SELECT t.*
FROM tab t
JOIN (SELECT orderid, COUNT(DISTINCT userid)
FROM tab
GROUP BY orderId
HAVING COUNT(DISTINCT userid) > 1) AS sub
ON t.orderid = sub.orderid
ORDER BY t.id
If you want to get just the rows that have same orderid but different userid, use this:
SELECT P1.* FROM points P1
INNER JOIN points P2
ON P1.orderid = P2.orderid and P1.id != P2.id and P1.userid != p2.userid;
Note that this first select returns what you expect in your question:
+----+--------+---------+
| id | userid | orderid |
+----+--------+---------+
| 4 | 12 | 152 |
| 5 | 11 | 152 |
+----+--------+---------+
Now, if you want to return ANY orderid that is the same, regardless of userid, use this:
SELECT P1.* FROM points P1
INNER JOIN points P2
ON P1.orderid = P2.orderid and P1.id != P2.id;
In this case, it won't exclude the result with same id, returning
+----+--------+---------+
| id | userid | orderid |
+----+--------+---------+
| 1 | 10 | 150 |
| 2 | 10 | 150 |
| 4 | 12 | 152 |
| 5 | 11 | 152 |
+----+--------+---------+
I have the following data structure:
Table 1(groups):
ID | Group
=============
1 | Sample
2 | Data
Table 2(items):
ID | GroupID | Cost | Amount
==============================
1 | 1 | 1 | 12
2 | 1 | 7 | 15
3 | 1 | 3 | 8
4 | 2 | 2 | 12
And would like the following (query) results:
groups.ID | groups.Name | total
1 | Sample | 141
2 | Data | 24
total is the sum over the products of cost and amount of all items in the group i.e. for group 1: 1*12+7*15+3*8=141
Im guessing I have to something with
SELECT g.ID, g.Group, SUM(Products)
FROM groups AS g, items AS i
WHERE g.ID=i.GroupID
GROUP BY i.GroupID
But don't know what exactly.
Doing iit in clientsoftware with loops is no problem, but I am curious (and certain) that this can be done in (my)Sql
SELECT g.ID as ID, g.Group as Name, SUM(i.Cost * i.Amount) as total
FROM groups g
INNER JOIN items i ON i.GroupID = g.ID
GROUP BY g.Group, g.ID
Having a field named "Group" is quite a bad idea in SQL (reserved keyword)
Working with a database structure I didn't create and hoping for some help on a simple MySQL query. I have a voting table votes with these fields:
vote_id = unique vote identifier
item_id = id of the entry voted on
voter_id = the id of the member who entered the vote
vote_date = the date of the vote
vote = the type of vote (1 or 2)
Each user can vote multiple times on a site entry specified by item_id. They can place a vote of 1 which is a "like" vote, or a vote of 2 which is an "unlike" vote. Each time they vote, a new record is created. I would like to be able to find the most recent vote value for each user on a particular item_id and then be able to actually SUM or COUNT the vote column IF the vote value is a "like" (value of 1)
For example
vote_id item_id voter_id vote_date vote
60 9 27 1273770151 1
153 9 45 1274896188 1
163 9 3 1274918584 1
164 9 3 1275021495 2
1051 9 181 1290839090 1
I want to get the newest vote values for each user, and then do a count of how many votes of 1 there are. In this case, the # would be 3
27 = 1
45 = 1
3 = 2
181 = 1
3
Ideally once I have a "score" for each item_id, the query would be able to SUM the score of each one into a total # of ALL current "likes" on the site.
Thanks for any help with this. I did my best to find an answer to this by searching but nothing was exactly right.
Much appreciated.
[EDIT:] I added values (1052, 10, 3, 1290839091, 1) to better exercise the problem, and had to add "item_id" to the sub-query that extracts newest votes.
Yay! Finally a stackoverflow question I can actually answer!!! I've been browsing around for a week looking for something short & sweet & up my alley. Thanks for a fun SQL problem!
First, you need to extract the newest votes. The combination of (voter_id, item_id, vote_date) better be unique for this approach to work!
SELECT
voter_id, item_id, MAX(vote_date) AS vote_date
FROM
votes
GROUP BY
voter_id, item_id
Results:
+----------+---------+------------+
| voter_id | item_id | vote_date |
+----------+---------+------------+
| 3 | 9 | 1275021495 |
| 3 | 10 | 1290839091 |
| 27 | 9 | 1273770151 |
| 45 | 9 | 1274896188 |
| 181 | 9 | 1290839090 |
+----------+---------+------------+
And then you need to join the original table against these results. A sub-select will do the job. Notice how the query above is copy & pasted into the join below, but now it's given the name "tmp":
SELECT
v.*
FROM (
SELECT
voter_id, item_id, MAX(vote_date) AS vote_date
FROM
votes
GROUP BY
voter_id, item_id
) tmp
INNER JOIN
votes v ON ( v.vote_date = tmp.vote_date
AND v.voter_id = tmp.voter_id
AND v.item_id = tmp.item_id
)
Results:
+---------+---------+----------+------------+------+
| vote_id | item_id | voter_id | vote_date | vote |
+---------+---------+----------+------------+------+
| 60 | 9 | 27 | 1273770151 | 1 |
| 153 | 9 | 45 | 1274896188 | 1 |
| 164 | 9 | 3 | 1275021495 | 2 |
| 1051 | 9 | 181 | 1290839090 | 1 |
| 1052 | 10 | 3 | 1290839091 | 1 |
+---------+---------+----------+------------+------+
I trust you know what to do from here.... oh darn it, I can't help myself, this is too cute:
SELECT
v.item_id, SUM(2 - v.vote) AS likes, SUM(v.vote - 1) AS dislikes
FROM (
SELECT
voter_id, item_id, MAX(vote_date) AS vote_date
FROM
votes
GROUP BY
voter_id, item_id
) tmp
INNER JOIN
votes v ON ( v.vote_date = tmp.vote_date
AND v.voter_id = tmp.voter_id
AND v.item_id = tmp.item_id
)
GROUP BY
v.item_id
Results:
+---------+-------+----------+
| item_id | likes | dislikes |
+---------+-------+----------+
| 9 | 3 | 1 |
| 10 | 1 | 0 |
+---------+-------+----------+
Unsure of the question, is this what you're looking for?
SELECT COUNT(*) FROM votes WHERE vote = '1' AND item_id = '9'