I have a mysql table like this
id |code|price|quantity
1 |0001|10.00|1
2 |0001|10.00|1
3 |0001|15.00|3
4 |0001|15.00|1
5 |0002| 5.00|2
6 |0002| 5.00|1
Using the functions concat and group_concat I got this result:
SELECT code, group_concat( CONCAT( quantity, 'x', FORMAT(price, 2 ))SEPARATOR '+' ) AS sales
FROM detalle_sales
GROUP BY code
code|sales
0001|1x10,00+1x10,00+3x15.00+1x15.00
0002|2x5.00+1x5.00
How can I group the quantities by the price using mysql?
code|sales
0001|2x10.00+4x15.00
0002|3x5.00
I've done it by php but when the sales field is too long, the result is truncated and gives an inaccurate value.
You need a subquery that groups all the rows with the same price together, then a main query that performs the GROUP_CONCAT by code.
SELECT code, group_concat( CONCAT( quantity, 'x', FORMAT(price, 2 ))SEPARATOR '+' ) AS sales
FROM (
SELECT code, price, SUM(quantity) as quantity
FROM detalle_sales
GROUP by code, price) AS subq
GROUP BY code
DEMO
While I consider it a not-so-good idea to create this sort of format in the DB, here is how it goes:
SELECT code, group_concat( CONCAT( total, 'x', FORMAT(price, 2 ))SEPARATOR '+' ) AS sales
FROM (
SELECT
code, price,
SUM(quantity) AS total
FROM detalle_sales
GROUP BY code, price
) AS baseview
GROUP BY code
Related
Decided to break my query in to bits, to help communicate what I am trying to achieve.
I have some information about a Customer and the Coupon Code they've used, in this format
Customer
Coupon Code
1
FreeDel
1
FreeDel
1
FreeDel
1
1562733
1
8842939
1
847hr64
1
83jd63j
1
FreeDel
1
8eh33jr
1
AA-2637
1
AA-9837
1
Save200
1
Save200
I want to sort it so that: If a known coupon-code prefix is available, then using syntax like this:
CASE WHEN Coupon Code LIKE 'AA-%' THEN 'AA-'
CASE WHEN Coupon Code IS UNIQUE THEN 'UNIQUE'
CASE WHEN Coupon Code IS NOT UNIQUE THEN 'NON-UNIQUE'
And so to output
Count
Customer
Coupon Code Type
6
1
Non-Unique
2
1
AA-
5
1
Unique
In this ideal, the known prefixes are added first as cases, and then unknown, unrepeated Coupon Codes are labelled Unique and then repeated Coupon Codes are labelled Non-Unique.
Any help would be super appreciated! :)
Table edits
You could count them separately:
select sum(cnt), customer, 'Non-Unique'
from (
select customer, coupon_code, count(*) as cnt
from ccodes
where coupon_code not like 'AA-%'
group by customer, coupon_code
having cnt>1
) as q
group by customer
union
select count(*), customer, 'AA-'
from ccodes
where coupon_code like 'AA-%'
group by customer
union
select sum(cnt), customer, 'Unique'
from (
select customer, coupon_code, count(*) as cnt
from ccodes
where coupon_code not like 'AA-%'
group by customer, coupon_code
having cnt=1
) as q
group by customer
See db-fiddle
You can use aggregation and conditional logic:
(case when sum( code like 'AA-%' ) > 0 then 'AA-'
when min(code) = max(code) then 'UNIQUE'
else 'NON-UNIQUE'
end)
You can incorporate this into an aggregation query as:
select grp, count(*)
from (select c.customer,
(case when sum( code like 'AA-%' ) > 0 then 'AA-'
when min(code) = max(code) then 'UNIQUE'
else 'NON-UNIQUE'
end) as grp,
count(*)
from c
group by customer
) x
group by grp;
I have the following query that is grabbing data from a table and combining all the products into one column and counting the quantity of that order.
I need to add an additional column to the output though, how can I also add ship_date?
select order_id, group_concat(product_id, ' - ', cnt separator ', ') as products, sum(cnt) as total
from (select order_id, product_id, count(*) as cnt
from tt_order_items
group by order_id, product_id
) op
group by order_id;
This is how the original table is laid out:
And this is how the query outputs the results:
How can I add ship_date to that output?
It looks like ship_date is fixed for each and every order_id. If so, you can just add it to the inner and outer aggregation:
select
order_id,
group_concat(product_id, ' - ', cnt separator ', ') as products,
sum(cnt) as total,
ship_date
from (
select order_id, product_id, count(*) as cnt, ship_date
from tt_order_items
group by order_id, product_id, ship_date
) op
group by order_id, ship_date;
SQL Fiddle
Table scheme:
CREATE TABLE company
(`company_id` int,`name` varchar(30))
;
INSERT INTO company
(`company_id`,`name`)
VALUES
(1,"Company A"),
(2,"Company B")
;
CREATE TABLE price
(`company_id` int,`price` int,`time` timestamp)
;
INSERT INTO price
(`company_id`,`price`,`time`)
VALUES
(1,50,'2015-02-21 02:34:40'),
(2,60,'2015-02-21 02:35:40'),
(1,70,'2015-02-21 05:34:40'),
(2,120,'2015-02-21 05:35:40'),
(1,150,'2015-02-22 02:34:40'),
(2,130,'2015-02-22 02:35:40'),
(1,170,'2015-02-22 05:34:40'),
(2,190,'2015-02-22 05:35:40')
I'm using Cron Jobs to fetch company prices. In concatenating the price history for each company, how can I make sure that only the last one in each day is included? In this case, I want all of the price records around 05:30am concatenated.
This is the result I'm trying to get (I have used Date(time) to only get the dates from the timestamps):
COMPANY_ID PRICE TIME
1 70|170 2015-02-21|2015-02-22
2 120|190 2015-02-21|2015-02-22
I have tried the following query but it doesn't work. The prices don't correspond to the dates and I don't know how to exclude all of the 2:30 am records before applying the Group_concat function.
SELECT company_id,price,trend_date FROM
(
SELECT company_id, GROUP_CONCAT(price SEPARATOR'|') AS price,
GROUP_CONCAT(trend_date SEPARATOR'|') AS trend_date
FROM
(
SELECT company_id,price,
DATE(time) AS trend_date
FROM price
ORDER BY time ASC
)x1
GROUP BY company_id
)t1
Can anyone show me how to get the desired result?
Ok, so this should work as intended:
SELECT p.company_id,
GROUP_CONCAT(price SEPARATOR '|') as price,
GROUP_CONCAT(PriceDate SEPARATOR '|') as trend_date
FROM price as p
INNER JOIN (SELECT company_id,
DATE(`time`) as PriceDate,
MAX(`time`) as MaxTime
FROM price
GROUP BY company_id,
DATE(`time`)) as t
ON p.company_id = t.company_id
AND p.`time` = t.MaxTime
GROUP BY p.company_id
Here is the modified sqlfiddle.
This is a bit unorthodox but I think it solves your problem:
SELECT company_id,
GROUP_CONCAT(price SEPARATOR'|'),
GROUP_CONCAT(trend_date SEPARATOR'|')
FROM (
SELECT *
FROM (
SELECT company_id,
DATE(`time`) `trend_date`,
price
FROM price
ORDER BY `time` DESC
) AS a
GROUP BY company_id, `trend_date`
) AS b
GROUP BY company_id
Before anyone comments, I did not design this database with comma separated values :)
I have spent time trying to find the answer but all I could find was GROUP_CONCAT() which seemed to do the opposite of what I wanted.
I would like to GROUP BY each of the values within the comma separated value field.
SELECT round(avg(DATEDIFF( dateClosed , dateAded ) * 1.0), 2) AS avg, department
FROM tickets GROUP BY assignedto
the assignedto field is the comma separated value field
row1 54,69,555
row2 54,75,555
row3 75,555
DESIRED OUTPUT: an average rounded figure for each value in assignedto field grouped.
EDIT - TRYING TO TAKE THIS TO THE NEXT LEVEL:
I want to include the ticket answer table to get the first response for that ticket, use its datetime field to work out the average response time for each user.
SELECT a.id as theuser, round(avg(DATEDIFF( ta.dateAded , t.dateAded ) * 1.0), 2) as avg
FROM tickets t join
mdl_user a
on find_in_set(a.id, t.assignedto) > 0
INNER JOIN (SELECT MIN(ta.dateAded) as started FROM ticketanswer GROUP BY ta.ticketId) ta ON t.id = ta.ticketId
GROUP BY a.id ORDER BY avg ASC
Yuck. You can do this, assuming you know the maximum number of assignments. Here is an approach:
select substring_index(substring_index(assignedto, ',', n.n), ',', -1) as assignedto,
round(avg(DATEDIFF( dateClosed , dateAded ) * 1.0), 2) as avg
from tickets t join
(select 1 as n union all select 2 union all select 3)
on length(assignedto) - length(replace(assignedto, ',', '')) < n.n
group by substring_index(substring_index(assignedto, ',', n.n), ',', -1);
Or, an easier way if you have a list of assigned values, say in an AssignedTo table:
select a.assignedto, round(avg(DATEDIFF( dateClosed , dateAded ) * 1.0), 2) as avg
from tickets t join
assignedto a
on find_in_set(a.assignedto, t.assignedto) > 0
group by a.assignedto;
I'm sorry you have to deal with this malformed database structure.
I have this mysql table:
DATE | VALUE
and I wish to become a select which shows me this information as:
DATE | COUNT TOTAL | COUNT VAL=1 | COUNT VAL=2
Any ideas how I can achieve this?
SELECT date,
COUNT(*),
COUNT( IF( value = 1, 1, NULL ) ),
COUNT( IF( value = 2, 1, NULL ) )
FROM my_table
I think with SUM() you can get neater code. Since it sums the values respective expression for row.
SELECT date,
COUNT(*),
SUM( value = 1 ),
SUM( value = 2 )
FROM my_table
Official Documentation can be found here.
SELECT `date`, COUNT(*) AS `COUNT TOTAL`,
COUNT(CASE `value` WHEN 1 THEN `value` END) AS `COUNT VAL=1`
COUNT(CASE `value` WHEN 2 THEN `value` END) AS `COUNT VAL=2`
FROM mytable
GROUP BY `date`
The CASE expressions will be null when there is no match. Nulls are not counted by COUNT().
I imagine you might want a dynamic number of columns, one column for each value found in the data. This is not possible in SQL. The columns must be known at the time you write the query.
So you have two options to get subtotals per value:
First query the distinct values from all rows of value and construct an SQL query dynamically, appending one column in the select-list for each distinct value you want to report. Then run this SQL query.
Alternatively, fetch all the rows as rows. Count the subtotals per value in application code.
One further alternative is to count subtotals by groups, and include totals:
SELECT `value`, `date, COUNT(*) AS `COUNT SUBTOTAL`
FROM mytable
GROUP BY `value`, `date` WITH ROLLUP
But that doesn't report the subtotals in columns as you requested, it reports the subtotals in rows.