mysql get total values and total number from where clause - mysql

I'm trying to write a mysql query which will return the total number of values from a column and also the total number of values based on a where clause from the same column.
I have a table like this:
+------------------------+-------+
| color | code |
+------------------------+-------+
| red | 200 |
| red | 202 |
| blue | 105 |
| yellow | 136 |
| green | 561 |
| red | 198 |
| blue | 414 |
| green | 11 |
| yellow | 600 |
| green | 155 |
| red | 865 |
| blue | 601 |
| green | 311 |
+------------------------+-------+
If I run this query:
select
color,
count(*) as count
from colors
where code > 0 &&
code <= 500
group by color
order by count(*) desc;
I get this result which is great because it's almost what I want:
+------------------------+-------+
| color | count |
+------------------------+-------+
| red | 3 |
| green | 3 |
| blue | 2 |
| yellow | 1 |
+------------------------+-------+
What I also need returned is the total number of values in the column, so the result table would look like this.
+------------------------+--------------+-------+
| color | total | count |
+------------------------+--------------+-------+
| red | 4 | 3 |
| green | 4 | 3 |
| blue | 3 | 2 |
| yellow | 2 | 1 |
+------------------------+--------------+-------+
So the total is the number of each value in the color column and count is the total amount which matches the where clause.
Thanks :)
Here is the link to SQLFiddle.
http://sqlfiddle.com/#!9/777f93/2

You need to use conditional aggregation to handle the counts and let the engine handle the total.
SELECT color
, count(*) as Total
, sum(case when code > 0 and code <= 500 then 1 else 0 end) as cnt
FROM colors
GROUP BY color
ORDER BY cnt desc;

You can use conditional aggregation:
select color,
count(*) as Total,
sum(code > 0 and code <= 500) as count_0_to_500
from colors
group by color
order by count_0_to_500 desc
It uses the fact that true evaluates to 1 and false evaluates to 0 in MySQL.
It's basically what xQbert answered just without a case expression.

You can JOIN your query with another query, e.g.:
select color, count(*) as count , a.total
from colors JOIN (
SELECT color, count(*) as `total` FROM colors GROUP BY color
) a ON colors.code = a.color
where code > 0 && code <= 500
group by color
order by count(*) desc;

You case use a case when statement to count only those items that meet your criteria. Like this:
Select
color
, count(*) as total
, SUM(CASE WHEN code > 0 && code <= 500 THEN 1 ELSE 0 END ) as Count
group by color order by count(*) desc;

You can do it using join query and table alias
select t1.color,t1.total,t2.count
FROM
(select color, count(*) as total from colors group by color) t1,
(select color, count(*) as `count` from colors where `code` > 0 && `code` <= 500 group by color) t2
WHERE
t1.color=t2.color order by `count` desc;
Here is the link to SQLFiddle.
http://sqlfiddle.com/#!9/777f93/2

Related

MYSQL search multiple condition in one column

table1
-------------------------------
| id | color | shape |
|------------------------------
| 1 | green | triangle |
| 2 | green | square |
| 3 | blue | rectangle |
| 4 | white | sphere |
| 5 | yellow | triangle |
-------------------------------
I want to get a result where row has multiple condition focusing in one column.
Here is my code.
SELECT * FROM table1 WHERE shape = 'triangle' and shape = 'square';
However, result should have the same value in column color.
Is it possible to have a result as below?
-------------------------------
| id | color | shape |
|------------------------------
| 1 | green | triangle |
| 2 | green | square |
-------------------------------
One option uses not exists:
select t.*
from mytable t
where
shape in ('triangle', 'square')
and exists (
select 1
from mytable t1
where
t1.shape in ('triangle, 'square')
and t1.color = t.color
and t1.shape <> t.shape
)
If you are running MySQL 8.0, you can also use window functions. Assuming that there are no duplicates in (color, shape) tuples:
select id, color, shape
from (
select t.*, count(*) over(partition by color) cnt
from mytable t
where shape in ('triangle', 'square')
) t
where cnt > 1

MySQL SUM only if one of the columns contain a certain value

Is there a way to sum rows only when one of the columns has a certain value? I have this table:
| order_id | total | is_tip |
-----------------------------
| 1 | 12 | 1 |
| 1 | 3 | 0 |
| 2 | 28 | 0 |
| 2 | 15 | 0 |
| 3 | 39 | 1 |
| 3 | 8 | 1 |
The desired result would be:
| order_id | SUM(total) |
-------------------------
| 1 | 15 |
| 3 | 47 |
It would only sum up if one of the is_tip columns is equal to 1. So order IDs 1 and 3 are qualified. So far I've tried to use this query:
SELECT order_id, SUM(total) FROM orders HAVING COUNT(is_tip) >= 1;
But this query is so wrong. I'm just a beginner. Thank you in advance.
Use a having clause:
SELECT order_id, SUM(total)
FROM orders
GROUP BY order_id
HAVING SUM(is_tip) >= 1;
Your query also needs a GROUP BY. And I'm assuming you want a row with at least one "tip". You can also phrase the HAVING clause as:
HAVING MAX(is_tip) > 0
Please use below query,
SELECT order_id, SUM(total) FROM orders where is_tip >= 1 group by order_id;
Having can be used only where you want to filter on aggregation basis

Does TOP function not work the same way as LIMIT in mysql?

Data
+----+-----------+--------------+------------+--------+------------+
| id | action | question_id | answer_id | q_num | timestamp |
+----+-----------+--------------+------------+--------+------------+
| 5 | "show" | 285 | null | 1 | 123 |
| 5 | "answer" | 285 | 124124 | 1 | 124 |
| 5 | "show" | 369 | null | 2 | 125 |
| 5 | "skip" | 369 | null | 2 | 126 |
+----+-----------+--------------+------------+--------+------------+
MYSQL
select question_id as survey_log
from
(
SELECT sum(CASE WHEN action='answer' THEN 1 ELSE 0 END) as num,
question_id,
count(distinct id) as den
from
survey_log
group by question_id
) b
order by (num/den) desc
limit 1
Output
285
MSSQL
select top 1 question_id as survey_log
from
(
SELECT sum(CASE WHEN action='answer' THEN 1 ELSE 0 END) as num,
question_id,
count(distinct id) as den
from
survey_log
group by question_id
) b
order by (num/den) desc
Output
369
For most of the scenarios, I used top 1 and limit 1 for similar results until this question. Somehow in this query, I get different results. Where am I going wrong? Is the order of execution different in MSSQL for TOP clause? Or I'm totally confusing the use-case of the two?
Original Question from Leetcode
In SQL Server, the division of two integers is an integer. So, 1/2 = 0, not 0.5.
To fix this, use:
order by num * 1.0 / den
In addition, if there are duplicate values for the order by key, then an arbitrary equivalent row will be returned.

MySQL order by index and then duplicates together

I want to have the rows sorted by ID and then have the duplicates appear sequentially.
Example:
id color
1 red
2 green
3 yellow
4 green
5 green
6 red
Expected:
id color
1 red
6 red
2 green
4 green
5 green
3 yellow
If you are on MySql 8.0+ you can use MIN() window function:
select t.id, t.color
from (
select *,
min(id) over (partition by color) minid
from tablename
) t
order by t.minid, id
For previous versions:
select t.* from tablename t
order by (select min(id) from tablename where color = t.color), id;
See the demo.
Results:
| id | color |
| --- | ------ |
| 1 | red |
| 6 | red |
| 2 | green |
| 4 | green |
| 5 | green |
| 3 | yellow |

Group Concat in mysql statement

I've got a table called delitems with some colums.
Within my SELECT statement I want to use a GROUP_CONCAT:
+-------------------------------+-------+--------+--------+-----+
| COLOR | tOTAL | Ptotal | Amount | qty |
+-------------------------------+-------+--------+--------+-----+
| BLUE - W = 55,BLUE - W/O = 93 | 148 | 375 | 55500 | 2 |
+-------------------------------+-------+--------+--------+-----+
mysql>select GROUP_CONCAT(color,' = ',qty) as COLOR, SUM(qTY) AS tOTAL, suM(p_cost) as Ptotal, SUM(qty)*SUM(p_cost) as Amount,count(*) qty from delitems where status='3' Group By cont_no;
Everything works fine except the Amount column. The total amount is wrong! Here the correct value:
+-----------------+-------+--------+--------+-----+
| COLOR | tOTAL | Ptotal | Amount | qty |
+-----------------+-------+--------+--------+-----+
| BLUE - W = 55 | 55 | 125 | 6875 | 1 |
| BLUE - W/O = 93 | 93 | 250 | 23250 | 1 |
+-----------------+-------+--------+--------+-----+
mysql>select GROUP_CONCAT(color,' = ',qty) as COLOR, SUM(qTY) AS tOTAL, suM(p_cost) as Ptotal, SUM(qty)*SUM(p_cost) as Amount,count(*) qty from delitems where status='3' Group By color;
I only want to display it in one line with the correct total amount
Please help.
Should be you need sum(a*b) not sum(a)*sum(b)
select
GROUP_CONCAT(color,' = ',qty) as COLOR
, SUM(qTY) AS tOTAL
, suM(p_cost) as Ptotal
, SUM(qty*(p_cost) as Amount, count(*) qty
from delitems
where status='3' Group By cont_no;