Mysql Group by second column if first column is equal? - mysql

I have a table that looks like this
id | rating
1 | 1
1 | 3
1 | 1
1 | 2
2 | 3
2 | 3
2 | 1
etc,you get the idea.
Anyway, I want to end up with this result set
id | rating | num
1 | 1 | 2
1 | 3 | 1
1 | 2 | 1
2 | 3 | 2
2 | 1 | 1
So, what I want to do is group the rating's together as long as the id is the same!
I thought I could just do group by id, rating and just assumed it would group only if both columns were the same, but it doesn't it groups if either column is the same so I end up with
id | rating | num
1 | 1 | 7
How can I solve this?

I don't understand the issue you are having. This query works for me:
select
id, rating, COUNT(rating) as num
FROM rating
GROUP BY id, rating
ORDER BY id, rating ASC;
And, just to be thorough, here is my entire test session:
mysql> create table rating (id int, rating int);
Query OK, 0 rows affected (0.04 sec)
mysql> insert into rating values (1,1),(1,3),(1,1),(1,2),(2,3),(2,3),(2,1);
Query OK, 7 rows affected (0.00 sec)
Records: 7 Duplicates: 0 Warnings: 0
mysql> select id, rating, COUNT(rating) as num FROM rating GROUP BY id, rating;
+------+--------+-----+
| id | rating | num |
+------+--------+-----+
| 1 | 1 | 2 |
| 1 | 2 | 1 |
| 1 | 3 | 1 |
| 2 | 1 | 1 |
| 2 | 3 | 2 |
+------+--------+-----+
5 rows in set (0.00 sec)

you could try
SELECT id,rating,COUNT(rating) AS num
FROM table1
GROUP BY id,rating
ORDER BY id ASC
SQLFiddle Demo

SELECT id,rating,count(rating) from table group by id,rating

Related

Mysql query, return only records which date is not overlapped with date of other records

To track orders i need order id from orders table and check orderdates table that order is made on specific date range. Using following query i can get id's but it will return id 3 also which is not needed.
Example: See orderdates table. First date of id 3 is overlapping with last date of id 2.
How i have to change query that id is not returned if it's first date is overlapping some other id's last date or is it even possible?
SELECT id
FROM orders
WHERE id in(
SELECT id
FROM orderdates
WHERE
orderdate BETWEEN '2017-06-01' AND '2017-06-30'
GROUP BY id);
orders
id sent
1 1
2 1
3 1
orderdates
id orderdate
1 2017-6-10
1 2017-6-11
1 2017-6-12
1 2017-6-13
2 2017-6-14
2 2017-6-15
2 2017-6-16
2 2017-6-17 <--- Last date of id 2
3 2017-6-17 <--- First date of id 3
3 2017-6-18
3 2017-6-19
3 2017-6-20
Maybe this where I compare the min date for every id against the max date for every id
select u.*
from t u
where u.id not in
(
select z.id
from
(
select s.*,t.id tid,t.mindt tmindt,t.maxdt tmaxdt
from
(
select id, min(dt) mindt,max(dt) maxdt
from t
group by id
order by id
) s
join
(select id, min(dt) mindt,max(dt) maxdt
from t
group by id
order by id
) t on
t.id <> s.id and
t.maxdt = s.mindt
) z
)
order by u.id,u.dt
given this
truncate table t;
insert into t values
(1,'2017-01-01'),(1,'2017-01-02'),
(2,'2017-01-03'),(2,'2017-01-04'),
(3,'2017-01-04')
results in
+------+------------+
| id | dt |
+------+------------+
| 1 | 2017-01-01 |
| 1 | 2017-01-02 |
| 2 | 2017-01-03 |
| 2 | 2017-01-04 |
+------+------------+
4 rows in set (0.00 sec)
given this
truncate table t;
insert into t values
(1,'2017-01-01'),(1,'2017-01-02'),
(2,'2017-01-03'),(2,'2017-01-04'),
(3,'2017-01-04'),
(4,'2017-01-04'),(4,'2017-01-06');
Result
+------+------------+
| id | dt |
+------+------------+
| 1 | 2017-01-01 |
| 1 | 2017-01-02 |
| 2 | 2017-01-03 |
| 2 | 2017-01-04 |
+------+------------+
4 rows in set (0.00 sec)
Given
truncate table t;
insert into t values
(1,'2017-01-01'),(1,'2017-01-02'),
(2,'2017-01-03'),(2,'2017-01-04'),
(3,'2017-01-04'),
(4,'2017-01-05'),(4,'2017-01-06');
result
+------+------------+
| id | dt |
+------+------------+
| 1 | 2017-01-01 |
| 1 | 2017-01-02 |
| 2 | 2017-01-03 |
| 2 | 2017-01-04 |
| 4 | 2017-01-05 |
| 4 | 2017-01-06 |
+------+------------+
6 rows in set (0.02 sec)

Limit with not operator is not working correctly MySql

I am using a query as below with not operator in where and limit. I am not able get correct sequencing of data (Without limit clause it is different and with limit ordering of data is something different).
SELECT DISTINCT(id) FROM `table` WHERE (1 AND id_type!=1) ORDER BY id desc LIMIT 2
Table Structure with sample data:
id id_type
1 1
2 1
3 2
4 3
5 3
6 3
Any Suggestions ?
Expected Output :
6
5
But When I remove the limit ordering is not same :
5
6
4
3
2
Note: This is just an sample data structure. Original table is contains much fields and different columns.
Maybe there is no problem at all. See this.
MariaDB [fbb]> SELECT * FROM `test`;
+----+---------+
| id | id_type |
+----+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 3 |
| 6 | 3 |
+----+---------+
6 rows in set (0.00 sec)
MariaDB [fbb]> SELECT DISTINCT(id) FROM `test` WHERE (1 AND id_type!=1) ORDER BY id desc LIMIT 2;
+----+
| id |
+----+
| 6 |
| 5 |
+----+
2 rows in set (0.00 sec)
MariaDB [fbb]>

mysqli SUM and MAX results

hi guys im having trouble understanding how to get a MAX() and a SUM() from a Database
my database have 3 colums id - stuff - score looks like this
id-stuf-score
1-1-2
1-1-3
1-2-1
1-2-3
1-3-1
1-3-3
i need to make a
MAX(score) where stuff=1 and id = 1
MAX(score) where stuff=2 and id = 1
MAX(score) where stuff=3 and id = 1
.
.
etc
and then a
SUM(score) all the MAX(score)
i have hundred of rows and i cant think of a way to make it happens
make subquery table derivatives for each thing you need the max of, then add them all together.
SELECT SUM(a.max+b.max+c.max) as total
FROM (
(
SELECT MAX(score) as max
FROM tablename
WHERE stuff = 1 AND id = 1
) as a,
(
SELECT MAX(score) as max
FROM tablename
WHERE stuff = 2 AND id = 1
) as b,
(
SELECT MAX(score) as max
FROM tablename
WHERE stuff = 3 AND id = 1
) as c
);
Output:
_____________
| total |
+-----------+
| 12345 |
+-----------+
Try using group by to get your max scores, then sum the results.
Records in Table
I added a few more records to so the max(score) wouldn't be the same for every stuf.
mysql> select * from stuff;
+------+------+-------+
| id | stuf | score |
+------+------+-------+
| 1 | 1 | 2 |
| 1 | 1 | 3 |
| 1 | 2 | 1 |
| 1 | 2 | 3 |
| 1 | 3 | 1 |
| 1 | 3 | 3 |
| 1 | 3 | 4 |
| 1 | 3 | 1 |
| 1 | 2 | 5 |
| 1 | 2 | 1 |
+------+------+-------+
10 rows in set (0.00 sec)
Group By
mysql> select id, max(score) as max_score from stuff group by stuf;
+------+-----------+
| id | max_score |
+------+-----------+
| 1 | 3 |
| 1 | 5 |
| 1 | 4 |
+------+-----------+
3 rows in set (0.00 sec)
Sum It Up
mysql> select sum(max_score) from (select id, max(score) as max_score
from stuff group by stuf) sum_me;
+----------------+
| sum(max_score) |
+----------------+
| 12 |
+----------------+
1 row in set (0.00 sec)
One Note
Keep in mind that if you have more ids then you will need to limit your query to whichever id you are interested in or appropriately group the last query.
mysql> select id, sum(max_score) from (select id, max(score) as max_score
from stuff group by id, stuf) sum_me group by id;
you can try this
SELECT SUM(a.max) as total
FROM (
(
SELECT MAX(score) as max
FROM tablename
GROUP BY stuf, id
) as a
);

Make new column which is incremented by it's order

I need to make new column for my table Products -> called Order (new column). And using rails migration I need to add new column and instantly set it's order number, but it's need to be done by product_id.
What I mean I need something like:
product_id | order
1 ------------> 1
1 ------------> 2
1 ------------> 3
2 ------------> 1
2 ------------> 2
Is there a way of doing it?
EDIT :
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''order' = t1.'order'' at line 15:
update product_submissions t
join (
select
id,
product_id,
'order' from (
select id,
product_id,
#rn:= if(#prev = product_id,#rn:=#rn+1,1) as 'order',
#prev:=product_id
from product_submissions,
(select #rn:=0,#prev:=0)r
order by product_id,id
)x
)t1 on t1.id=t.id set t.'order' = t1.'order'
Consider the following
mysql> create table test (id int ,product_id int);
Query OK, 0 rows affected (0.14 sec)
mysql> insert into test values (1,1),(2,1),(3,1),(4,2),(5,2);
Now lets create the order
select
product_id,
`order` from (
select
product_id,
#rn:= if(#prev = product_id,#rn:=#rn+1,1) as `order`,
#prev:=product_id from test,(select #rn:=0,#prev:=0)r
order by product_id,id
)x ;
This will give you something as
+------------+-------+
| product_id | order |
+------------+-------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
+------------+-------+
Now lets use in update command, but before that lets add the column (in your case its already there)
mysql> alter table test add column `order` int ;
Query OK, 5 rows affected (0.29 sec)
mysql> select * from test ;
+------+------------+-------+
| id | product_id | order |
+------+------------+-------+
| 1 | 1 | NULL |
| 2 | 1 | NULL |
| 3 | 1 | NULL |
| 4 | 2 | NULL |
| 5 | 2 | NULL |
+------+------------+-------+
5 rows in set (0.00 sec)
Finally the update command
update test t
join (
select
id,
product_id,
`order` from (
select id,
product_id,
#rn:= if(#prev = product_id,#rn:=#rn+1,1) as `order`,
#prev:=product_id
from test,(select #rn:=0,#prev:=0)r
order by product_id,id
)x
)t1 on t1.id=t.id set t.`order` = t1.`order`
mysql> select * from test ;
+------+------------+-------+
| id | product_id | order |
+------+------------+-------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 2 | 2 |
+------+------------+-------+
5 rows in set (0.00 sec)

mysql join extracted number

I have a 'big' table like this
id user type comment
6 1 A id '3' - #8
7 1 A id '3' - #9
8 3 B
9 3 B
I want to extract the numbers after the hash and join it with the id column to have the following (when the number between the single quotes is equal to the user)
id1 id2 user type
6 8 3 B
7 9 3 B
A create a copy of your table, its name is bigtable and insert those values that you gave us:
mysql> create table bigtable (id int, user_id int, type varchar(10), comment varchar(30));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into bigtable values (6,1, 'A', 'id 3 - #8'),(7,1,'A', 'id 3 - #9'),(8,3, 'B','' ),(9,3, 'B','');
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from bigtable;
+------+---------+------+-----------+
| id | user_id | type | comment |
+------+---------+------+-----------+
| 6 | 1 | A | id 3 - #8 |
| 7 | 1 | A | id 3 - #9 |
| 8 | 3 | B | |
| 9 | 3 | B | |
+------+---------+------+-----------+
4 rows in set (0.00 sec)
I did a self join and use the substrn_index function:
mysql> select b1.id,b2.id,b1.user_id,b1.type
from bigtable as b1 join bigtable as b2
on b1.id=SUBSTRING_INDEX(b2.COMMENT,'#',-1);
+------+------+---------+------+
| id | id | user_id | type |
+------+------+---------+------+
| 8 | 6 | 3 | B |
| 9 | 7 | 3 | B |
+------+------+---------+------+
2 rows in set (0.00 sec)
I hope this helped you