I have following table in MySQL:
some_table
user_id | obj_id
-----------------
5 | 1
6 | 1
7 | 2
8 | 2
Now I need a Query, which will get me the obj_id, if this obj_id has both user_id = 5 and user_id = 6 (in the example above it is obj_id=1).
Is something like this possible with MySQL?
One method uses group by and having:
select obj_id
from some_table t
where user_id in (5, 6)
group by obj_id
having count(distinct user_id) = 2;
As #GordonLinoff already provided a better solution.
But this is one of the possible way to get your expected result using INTERSECT:
SELECT DISTINCT obj_id FROM #TEST WHERE user_id = 5
INTERSECT
SELECT DISTINCT obj_id FROM #TEST WHERE user_id = 6
Sample execution:
CREATE TABLE some_table (`user_id` INT, obj_id INT);
INSERT INTO some_table (`user_id`, obj_id) VALUES
(5, 1),
(6, 1),
(7, 2),
(8, 2),
(5, 3),
(6, 4);
SELECT DISTINCT obj_id FROM some_table WHERE `user_id` = 5
INTERSECT
SELECT DISTINCT obj_id FROM some_table WHERE `user_id` = 6
Result will be 1.
Related
I am relatively new to SQL and I am trying to extract rows where they have the highest values.
For example, the table look like this:
user_id fruits
1 apple
1 orange
2 apple
1 pear
I would like to extract the data such that it would look like this:
user_id fruits
1 3
If user_id 2 has 3 fruits, it should display:
user_id fruits
1 3
2 3
I can only manage to get the if I use LIMIT = 1 by DESC order, but that is not the right way to do it. Otherwise I am getting only:
user_id fruits
1 3
2 1
Not sure where to store the max value to put in the where clause. Appreciate any help, thank you
Use RANK():
WITH cte AS (
SELECT user_id, COUNT(*) AS cnt, RANK() OVER (ORDER BY COUNT(*) DESC) rnk
FROM yourTable
GROUP BY user_id
)
SELECT user_id, cnt AS fruits
FROM cte
WHERE rnk = 1;
Here's one answer (with sample data):
CREATE TABLE something (user_id INT NOT NULL, fruits VARCHAR(10) NOT NULL, PRIMARY KEY (user_id, fruits));
INSERT INTO something VALUES (1, 'apple');
INSERT INTO something VALUES (1, 'orange');
INSERT INTO something VALUES (2, 'apple');
INSERT INTO something VALUES (1, 'pear');
INSERT INTO something VALUES (2, 'orange');
INSERT INTO something VALUES (2, 'pear');
SELECT user_id, COUNT(*) AS cnt
FROM something
GROUP BY user_id
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM something GROUP BY user_id);
I have three tables.
For each "id" value, I would like the sum of the col1 values, the sum of col2 values & the sum of col3 values listed separately. I am not summing across tables.
table a
num | id | col1
================
1 100 0
2 100 1
3 100 0
1 101 1
2 101 1
3 101 0
table b
idx | id | col2
=================
1 100 20
2 100 20
3 100 20
4 101 100
5 101 100
table c
idx | id | col3
==============================
1 100 1
2 100 1
3 100 1
4 101 10
5 101 1
I would like the results to look like this,
ID | sum_col1 | sum_col2 | sum_col3
====================================
100 1 60 3
101 2 200 11
Here is my query which runs too long and then times out. My tables are about 25,000 rows.
SELECT a.id as id,
SUM(a.col1) as sum_col1,
SUM(b.col2) as sum_col2,
SUM(c.col3) as sum_col3
FROM a, b, c
WHERE a.id=b.id
AND a=id=c.id
GROUP by id
Order by id desc
The number of rows in each table may be different, but the range of "id" values in each table is the same.
This appears to be a similar question, but I can't make it work,
Mysql join two tables sum, where and group by
Here is a solution based on your data. Issue with your query is that you were joining tables on a non-unique column resulting in Cartesian product.
Data
DROP TABLE IF EXISTS A;
CREATE TABLE A
(num int,
id int,
col1 int);
INSERT INTO A VALUES (1, 100, 0);
INSERT INTO A VALUES (2, 100, 1);
INSERT INTO A VALUES (3, 100, 0);
INSERT INTO A VALUES (1, 101, 1);
INSERT INTO A VALUES (2, 101, 1);
INSERT INTO A VALUES (3 , 101, 0);
DROP TABLE IF EXISTS B;
CREATE TABLE B
(idx int,
id int,
col2 int);
INSERT INTO B VALUES (1, 100, 20);
INSERT INTO B VALUES (2, 100, 20);
INSERT INTO B VALUES (3, 100, 20);
INSERT INTO B VALUES (4, 101, 100);
INSERT INTO B VALUES (5, 101, 100);
DROP TABLE IF EXISTS C;
CREATE TABLE C
(idx int,
id int,
col3 int);
INSERT INTO C VALUES (1, 100, 1);
INSERT INTO C VALUES (2, 100, 1);
INSERT INTO C VALUES (3, 100, 1);
INSERT INTO C VALUES (4, 101, 10);
INSERT INTO C VALUES (5, 101, 1);
Solution
SELECT a_sum.id, col1_sum, col2_sum, col3_sum
FROM (SELECT id, SUM(col1) AS col1_sum
FROM a
GROUP BY id ) a_sum
JOIN
(SELECT id, SUM(col2) AS col2_sum
FROM b
GROUP BY id ) b_sum
ON (a_sum.id = b_sum.id)
JOIN
(SELECT id, SUM(col3) AS col3_sum
FROM c
GROUP BY id ) c_sum
ON (a_sum.id = c_sum.id);
Result is as expected
Note: Do outer joins if an id doesnt have to be present in all three tables.
Maybe this will do?
Haven't got a chance to run it, but i think it can do the job.
SELECT sumA.id, sumA.sumCol1, sumB.sumCol2, sumC.sumCol3
FROM
(SELECT id, SUM(col1) AS sumCol1 FROM a GROUP BY id ORDER BY id ASC) AS sumA
JOIN (SELECT id, SUM(col2) AS sumCol2 FROM b GROUP BY id ORDER BY id ASC) AS sumB ON sumB.id = sumA.id
JOIN (SELECT id, SUM(col3) AS sumCol3 FROM c GROUP BY id ORDER BY id ASC) AS sumC ON sumC.id = sumB.id
;
EDIT
SELECT IF(sumA.id IS NOT NULL, sumA.id, IF(sumB.id IS NOT NULL, sumB.id, IF(sumC.id IS NOT NULL, sumC.id,''))),,
sumA.sumCol1, sumB.sumCol2, sumC.sumCol3
FROM
(SELECT id, SUM(col1) AS sumCol1 FROM a GROUP BY id ORDER BY id ASC) AS sumA
OUTER JOIN (SELECT id, SUM(col2) AS sumCol2 FROM b GROUP BY id ORDER BY id ASC) AS sumB ON sumB.id = sumA.id
OUTER JOIN (SELECT id, SUM(col3) AS sumCol3 FROM c GROUP BY id ORDER BY id ASC) AS sumC ON sumC.id = sumB.id
;
I would do the summing first, then union the results, then pivot them round:
SELECT
id,
MAX(CASE WHEN which = 'a' then sumof end) as sum_a,
MAX(CASE WHEN which = 'b' then sumof end) as sum_b,
MAX(CASE WHEN which = 'c' then sumof end) as sum_c
FROM
(
SELECT id, sum(col1) as sumof, 'a' as which FROM a GROUP BY id
UNION ALL
SELECT id, sum(col2) as sumof, 'b' as which FROM b GROUP BY id
UNION ALL
SELECT id, sum(col3) as sumof, 'c' as which FROM c GROUP BY id
) a
GROUP BY id
You could also union, then sum:
SELECT
id,
SUM(CASE WHEN which = 'a' then v end) as sum_a,
SUM(CASE WHEN which = 'b' then v end) as sum_b,
SUM(CASE WHEN which = 'c' then v end) as sum_c
FROM
(
SELECT id, col1 as v, 'a' as which FROM a GROUP BY id
UNION ALL
SELECT id, col2 as v, 'b' as which FROM b GROUP BY id
UNION ALL
SELECT id, col3 as v, 'c' as which FROM c GROUP BY id
) a
GROUP BY id
You cant easily use a join, unless all tables have all values of ID, in which case I'd say you can sum them as subqueries and then join the results together.. But if one of your tables suddenly lacks an id value that the other two tables have, that row disappears from your results (unless you use full outer join and some really ugly coalescing in your ON clause)
Using union in this case will give you a more missing-value-tolerant result set, as it can cope with missing values of ID in any table. Thus, we union the tables together into one dataset, but use a constant to track which table the value came from, that way we can pick it out into its own summation later
If any id value is not present in any table, then the sum for that column will be null. If you want it to be 0, you can change the MAX to SUM or wrap the MAX in a COALESCE
I have a table:
create table #t
(
ID int,
value nvarchar(5)
)
insert #t
values (1,'A'), (2, 'B'), (3, 'A'), (3, 'B')
Sample data:
ID value
------------
1 A
2 B
3 A
3 B
For my project I need the ID which has having both the values
Result :
ID
3
Kindly help me out.
To get IDs having 2 values
select id
from #t
group by id
having count(distinct value) >= 2
or to get all IDs having A and B
select id
from #t
where value in ('A','B')
group by id
having count(distinct value) = 2
or to make it more generic to get IDs having all values
select id
from #t
group by id
having count(distinct value) = (select count(distinct value) from #t)
Here how my tables look like:
CREATE TABLE my_table(id INT,user_id VARCHAR(5));
INSERT INTO my_table
VALUES
(1, 100),
(2, 200),
(3, 100),
(4, 150),
(5, 200),
(6, 300),
(7, 400),
(8, 500);
what i want
first of all,i need to check the query group by user_id , i got 100,150,200,300,400,500 then check each user_id get sets of its own id value. finally i want this answer user_id | sets 100 | 1,3 150 | 4 200 | 2,5 300 | 6 400 | 7 500 | 8 note: i need single query.please help me.
Try using GROUP_CONCAT function like
SELECT user_id,GROUP_CONCAT(id separator ",") as sets
FROM my_table
GROUP BY user_id;
See using GROUP_CONCAT() function.
Use GROUP_CONCAT function
select user_id, GROUP_CONCAT(id) as sets from your_table
group by user_id
You can try this:-
SELECT USER_ID AS USER, GROUP_CONCAT(ID) AS SETS FROM TABLE_NAME
GROUP BY USER_ID;
SELECT USER_ID AS USER, GROUP_CONCAT( ID ) AS SETS
FROM my_table
GROUP BY USER_ID
LIMIT 0 , 30
This is working with the database you provided
Just use a group by, with GROUP_CONCAT to lup the ids together
SELECT user_id, GROUP_CONCAT(id) AS sets
FROM my_table
GROUP BY user_id
ORDER BY user_id
I have a table like this:
someid somestring
1 Hello
1 World
1 Blah
2 World
2 TestA
2 TestB
...
Currently I'm grouping by the id and concatenating the strings, so I end up with this:
1 Hello,World,Blah
2 World,TestA,TestB
...
Is it possible to do a second grouping so that if there are multiple entries that end up with the same string, I can group those too?
Yes, just put your current query in an inner select and apply a new GROUP BY to the outer select. Note that you will probably want to use ORDER BY of GROUP_CONCAT to ensure that the strings are always concatenated in the same order.
SELECT somelist, COUNT(*) FROM
(
SELECT
someid,
GROUP_CONCAT(somestring ORDER BY somestring) AS somelist
FROM table1
GROUP BY someid
) AS T1
GROUP BY somelist
Result:
'Blah,Hello,World', 1
'TestA,TestB,World', 2
Here's the test data I used:
CREATE TABLE table1 (someid INT NOT NULL, somestring NVARCHAR(100) NOT NULL);
INSERT INTO table1 (someid, somestring) VALUES
(1, 'Hello'),
(1, 'World'),
(1, 'Blah'),
(2, 'World'),
(2, 'TestA'),
(2, 'TestB'),
(3, 'World'),
(3, 'TestB'),
(3, 'TestA');