How to use MYSQL GROUP BY SUM with multiple columns - mysql

Basically the question is how to get the sum from #hours, groupping by #id, #code, #semester, #year columns from this
id, hours, code, semester, year
165, 6, 3, 1, 2012
166, 6, 16, 1, 2012
460, 8, 14, 2, 2012
461, 8, 16, 2, 2012
462, 15, 16, 2, 2013
463, 6, 1, 2, 2013
id, hours, code, semester, year, sum
165, 6, 3, 1, 2012, **6**
166, 6, 16, 1, 2012, **6**
460, 8, 14, 2, 2012, **8**
461, 8, 16, 2, 2012, **23**
462, 15, 16, 2, 2012, **23**
463, 6, 1, 2, 2013, **6**
I have tried a lot with GROUP BY, GROUP BY CONCAT, etc, but no success.
I want to group by all these columns in each row

Try this:
select id, code, semester, year, sum(hours) from `table` group by id,code,semester, year

to sum a values of a column you can use SUM() function of MYSQL and you can return it as on of fields like this for example the field of sum in this query would be total_hours
SELECT id,hours,code,semester,year, SUM(hours) AS total_hours
FROM table_name
GROUP BY id,code,semester, year

Related

MYSQL get product records from history table for two different date with only latest data if duplicate found

I have a transaction table which holds different types of products which hold two types of products
which is stored in others field (json field) tagged as product_type1 and product_type2 and some
products can be tagged as both.
Transaction table:
id, hash_value, product_name,price, date , others
1, abc, product_name1, 20, 2018-10-21, {"product_type1": 1}
2, def, product_name2, 30, 2018-10-22, {"product_type2": 1}
3, ghi, product_name3, 40, 2018-10-21, {"product_type1": 1, "product_type2": 1}
Unique key (id, hash_value)
For the above mentioned table, we have a history table which stores the historical products
for the above products in transaction table (schema is same like transaction table , but unique key is on id,hash_value,date)
History table
id, hash_value, product_name, price, date , others
1, abc, product_name1, 20, 2018-10-21, {"product_type1": 1}
2, abc, product_name1, 18, 2018-10-20, {"product_type1": 1}
3, abc, product_name1, 19, 2018-10-19, {"product_type1": 1}
4, def, product_name2, 30, 2018-10-22, {"product_type2": 1}
4, def, product_name2, 29, 2018-10-21, {"product_type2": 1}
4, def, product_name2, 40, 2018-10-20, {"product_type2": 1}
5, ghi, product_name3, 40, 2018-10-21, {"product_type1": 1, "product_type2": 1}
5, ghi, product_name3, 50, 2018-10-22, {"product_type1": 1, "product_type2": 1}
I would like to query records with following condition.
1. Get all records tagged as product_type1 for date 2018-10-21
2. Get all records tagged as product_type2 for date 2018-10-22
3. If tagged as both then, get records having latest date.
The query i tried.
SELECT *
FROM ((SELECT *
FROM history_table
WHERE date = '2018-10-21'
AND others ->> '$.product_type1' == 1)
UNION ALL
(SELECT *
FROM history_table
WHERE date = '2018-10-22'
AND others ->> '$.product_type2' == 1))
but the result i get is
id, hash_value, product_name, price, date , others
1, abc, product_name1, 20, 2018-10-21, {"product_type1": 1}
4, def, product_name2, 30, 2018-10-22, {"product_type2": 1}
5, ghi, product_name3, 40, 2018-10-21, {"product_type1": 1, "product_type2": 1}
5, ghi, product_name3, 50, 2018-10-22, {"product_type1": 1, "product_type2": 1}
Result should only give record with latest date if duplicate record for id and hash_value exists
Results Expected:
id, hash_value, product_name, price, date , others
1, abc, product_name1, 20, 2018-10-21, {"product_type1": 1}
4, def, product_name2, 30, 2018-10-22, {"product_type2": 1}
5, ghi, product_name3, 50, 2018-10-22, {"product_type1": 1, "product_type2": 1}
In a Derived table (sub-select query), identify the maximum date value for a combination of id and hash_value matching the prescribed conditions.
Now, simply join this result-set to the history_table to get the rows corresponding to maximum date value only.
Instead of using Union All to combine two different conditional Select results; you can directly use OR in the Where condition here. it will be significantly more efficient.
Try the following query:
SELECT ht.* FROM
history_table AS ht
JOIN
(
SELECT id, hash_value, MAX(date) AS max_date
FROM history_table
WHERE (date = '2018-10-21' AND others ->> '$.product_type1' == 1)
OR
(date = '2018-10-22' AND others ->> '$.product_type2' == 1)
GROUP BY id, hash_value
) AS dt ON dt.id = ht.id AND
dt.hash_value = ht.hash_value AND
dt.max_date = ht.date

Group by rows order by min price first

I have a table 'terms':
([id], [t_id], [d_start], [d_end], [price], [departure_from])
with values:
(12,10, 2018-5-5, 2018-5-15, 95, london),
(11,10, 2018-5-5, 2018-5-15, 60, london),
(10,10, 2018-5-5, 2018-5-15, 90, london),
( 9, 10, 2018-5-5, 2018-5-15, 90, prag),
( 8, 10, 2018-5-5, 2018-5-15, 85, prag),
( 7, 10, 2018-5-5, 2018-5-15, 70, prag),
( 6, 10, 2018-6-8, 2018-6-18, 30, london),
( 5, 10, 2018-6-8, 2018-6-18, 20, london),
( 4, 10, 2018-6-8, 2018-6-18, 90, london),
( 3, 10, 2018-6-8, 2018-6-18, 90, prag),
( 2, 10, 2018-6-8, 2018-6-18, 10, prag),
( 1, 10, 2018-6-8, 2018-6-18, 70, prag);
and I want to group by d_start,d_end,departure_from with order by price and I want to order by price first.
I have query:
(SELECT * FROM
(SELECT * FROM terms
WHERE t_id=10 ORDER BY price) t
GROUP BY d_start,d_end,departure_from ORDER BY d_start)
Result I want: 4 rows with min price :
(11,10, 2018-5-5, 2018-5-15, 60, london),
( 7, 10, 2018-5-5, 2018-5-15, 70, prag),
( 5, 10, 2018-6-8, 2018-6-18, 20, london),
( 2, 10, 2018-6-8, 2018-6-18, 10, prag),
My first question there. Thank you for any help.
I found result that work for me:
(SELECT * FROM
(SELECT * FROM terms
WHERE t_id=10 GROUP BY d_start,d_end,departure_from,price ORDER BY d_start) t
GROUP BY d_start,d_end,departure_from)
What do you think? It's OK?
With the information you gave, the main problem you have is the variable names. Just add an `` for every of them.
Like:
SELECT * FROM
(SELECT * FROM terms
WHERE t_id=10 ORDER BY price)
GROUP BY `start`,`end`,`from` ORDER BY start
You need to use correlated subquery for this...
select t.*
from terms t
where t.price = (
select min(t2.price)
from terms t2
where t2.d_start = t.d_start
and t2.d_end = t.d_end
and t2.departure_from = t.departure_from
)
order by t.d_start;

MySQL: Aggregating counts

I'm trying to find how many companies had sales in a specific segment. I've managed to get a count of the sales entries (5), but I can't seem to aggregate by the product segment as well. Please see this simplification:
http://sqlfiddle.com/#!9/685cb/1
CREATE TABLE Table1
(`company` text, `sales` int, `segment` text)
;
INSERT INTO Table1
(`company`, `segment`, `sales`)
VALUES
('ACME',10,100),
('ACME',11,100),
('HAL',10,25),
('HAL',13,25),
('GEN',11,50)
;
SELECT COUNT(company) AS companies,
CASE
WHEN segment IN (10, 11, 12, 13, 14, 15, 16)
THEN 'Product segment A'
WHEN segment IN (20, 21, 22)
THEN 'Product segment B'
WHEN segment IN (30)
THEN 'Product segment C'
END AS grp, SUM(sales) AS sum_sales
FROM Table1
WHERE
(company LIKE '%ACME%'
OR company LIKE '%HAL%'
OR company LIKE '%GEN%'
)
AND
segment IN (10, 11, 12, 13, 14, 15 ,16, 20, 21, 22, 30)
GROUP BY grp
ORDER BY grp
;
The goal is to get "companies" to show 3, as there are three companies that had sales in segment A.
You could use the distinct modifier in the count function to get the number of different entries:
SELECT COUNT(DISTINCT company) AS companies,
-- Here -----^
CASE
WHEN segment IN (10, 11, 12, 13, 14, 15, 16)
THEN 'Product segment A'
WHEN segment IN (20, 21, 22)
THEN 'Product segment B'
WHEN segment IN (30)
THEN 'Product segment C'
END AS grp, SUM(sales) AS sum_sales
FROM Table1
WHERE
(company LIKE '%ACME%'
OR company LIKE '%HAL%'
OR company LIKE '%GEN%'
)
AND
segment IN (10, 11, 12, 13, 14, 15 ,16, 20, 21, 22, 30)
GROUP BY grp
ORDER BY grp
;
SQLFiddle

SQL - adding total by searching for another value relating to the amount

been given this problem to solve
Write a function to get the payment sales figures from any given shop. The shop should be searched for by name.
i have this so far
SELECT shopname SUM ( amount ) AS sales
FROM frs_Shop, frs_Payment
WHERE shopname = "shop name"
i have the amount to add up but when i go to compile it adds up every amount in this table
INSERT INTO frs_Payment
(payid, amount, paydatetime, empnin, custid, pstatusid, ptid)
values
(101, "3.99", "2015-10-26 16:26:15", "NIN001", 1, 1, 1),
(95, "15.96", "2015-09-24 16:26:15", "NIN001", 1, 1, 1),
(102, "3.99", "2015-10-11 13:25:31", "NIN003", 2, 1, 1),
(11, "11.97", "2015-06-12 19:37:59", "NIN010", 3, 1, 1),
(7, "11.97", "2015-04-11 12:41:28", "NIN010", 3, 2, 4),
(8, "7.98", "2015-05-05 22:49:02", "NIN010", 3, 1, 1),
(32, "15.96", "2015-07-19 02:26:49", "NIN024", 5, 2, 4),
(83, "7.98", "2015-08-20 16:21:08", "NIN011", 5, 2, 4),
(6, "15.96", "2015-03-04 10:51:03", "NIN027", 6, 2, 4),
(17, "3.99", "2015-10-03 01:06:15", "NIN028", 6, 1, 1),
(39, "11.97", "2015-03-24 20:03:05", "NIN027", 6, 1, 1),
(103, "3.99", "2015-10-27 14:45:11", "NIN009", 7, 1, 1),
(62, "15.96", "2015-10-12 14:23:23", "NIN001", 8, 1, 1),
i want it to only add up the ones i specify with the empnin
You can use an explicit join, and a GROUP BY. I made an assumption on the primary/foreign key relationship between frs_Shop and frs_Payment.
SELECT s.shopname
, p.empnin
, SUM ( p.amount ) AS sales
FROM frs_Shop s
INNER JOIN frs_Payment p on s.empnin = p.empnin
WHERE s.shopname = "shop name"
GROUP BY s.shopname, p.empnin

MySQL with Where IN and Distinct and Limit

SELECT id, server_id, start_time, end_time
FROM errors
WHERE server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
ORDER BY id DESC
LIMIT 9
This is the query I'm trying to run to give me results where the server_id = 3, 12, 24, 25, 26, 27, 28, 29, 30. Instead, what I receive is server_id = 25, 25, 12, 25, 27, 27, 28, 28, 27. Note the repeating server_ids. The query gives me unique id but duplicate server_id.
Is there a way I can get results that would show me the last id for each server_id?
I've tried doing ORDER BY server_id but that gives me the same issue.
I tried running DISTINCT but that also does not work.
you'll have to use some aggregation functions.
Something like
select
server_id,
max(id),
avg(start_time),--for example
avg(end_time)--for example
from errors
where server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
group by server_id
order by id desc
if you need tht start_time and end_time corresponding to the max id by server_id, you may do
select e.id, e.server_id, e.start_time, e.end_time
from errors e
join (select server_id, max(id) maxid
from errors
group by server_id) t
on t.maxid = e.id and e.server_id = t.server_id
where e.server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
order by e.id DESC
The issue you have is that you need only one record from each server with the max ID.. and relative information. You need to limit the results to just that max ID... Here's one way...
SELECT id, server_id, start_time, end_time
FROM errors
WHERE server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
and ID = (Select max(ID) from errors E2 where E2.server_ID=errors.server_ID)
ORDER BY id DESC
LIMIT 9