Ranking SUM of Value Column Grouped by Date - mysql

I have a query which I would like to add a ranking column. My existing query has three tables as a union query, with a sum of the total order value for that week. This query produces the sum of the total order value for that week, grouped by WeekCommencing, however I am struggling to add a ranking column based on the highest to the lowest total value for that week.
My (Updated) SQLFiddle example is here http://sqlfiddle.com/#!9/f1d43/35
CREATE and INSERT statements:
CREATE TABLE IF NOT EXISTS ORD (
WeekCommencing DATE,
Value DECIMAL(20 , 6 ),
Orders INT(6)
);
CREATE TABLE IF NOT EXISTS REF (
WeekCommencing DATE,
Value DECIMAL(20 , 6 ),
Orders INT(6)
);
CREATE TABLE IF NOT EXISTS SOH (
WeekCommencing DATE,
Value DECIMAL(20 , 6 ),
Orders INT(6)
);
INSERT INTO ORD (WeekCommencing, Value, Orders) VALUES
('2017-07-24',1,1),
('2017-07-31',2,1),
('2017-07-17',3,1);
INSERT INTO REF (WeekCommencing, Value, Orders) VALUES
('2017-07-24',4,1),
('2017-07-17',5,1),
('2017-07-31',6,1);
INSERT INTO SOH (WeekCommencing, Value, Orders) VALUES
('2017-07-17',7,1),
('2017-07-24',8,1),
('2017-07-31',9,1);
My best effort to date:
SELECT
WeekCommencing,
SUM(Value) AS 'TotalValue',
SUM(Orders) AS 'Orders',
#r:=#r+1 As 'Rank'
FROM
(SELECT
WeekCommencing, Value, Orders
FROM
ORD
GROUP BY WeekCommencing UNION ALL SELECT
WeekCommencing, Value, Orders
FROM
REF
GROUP BY WeekCommencing UNION ALL SELECT
WeekCommencing, Value, Orders
FROM
SOH
GROUP BY WeekCommencing) t1,
(SELECT #r:=0) Rank
GROUP BY WeekCommencing DESC;
My attempt currently ranks the order of week commencing, rather than the ranking highest to lowest.
My desired result is
WeekCommencing TotalValue Orders Rank
2017-07-31 17 3 1
2017-07-24 13 3 3
2017-07-17 15 3 2
Thanks is advance

SELECT a.*
, #i:=#i+1 rank
FROM
( SELECT weekcommencing
, SUM(value) totalvalue
, COUNT(*) totalorders
FROM
( SELECT weekcommencing, value, orders FROM ord
UNION ALL
SELECT weekcommencing, value, orders FROM ref
UNION ALL
SELECT weekcommencing, value, orders FROM soh
) x
GROUP
BY weekcommencing
) a
, (SELECT #i:=0) vars
ORDER
BY totalvalue DESC;

Related

my query doesn't return the max from value from the sum of working hours of the month

I want to find name of that persons who worked most in a month. but the query doesn't returning max value from sum of value
I'm new in mysql
SELECT
x.name,
sec_to_time(MAX(x.sum_time)) maximum
FROM (
SELECT
name,
SUM(TIME_TO_SEC(ending_time) - TIME_TO_SEC(starting_time)) sum_time
FROM working_hours wh, employees
WHERE wh.employees_id = employees.id
AND project_id IS NOT NULL
GROUP BY employees_id
) x
GROUP BY x.name;
this is my query. i want to show just name of that persons who worked most in a month. but it returns all persons who worked in a month
Try making these changes to your query:
change name to MAX(name)
qualify employees_id with wh.employees_id
SELECT
x.name,
sec_to_time(MAX(x.sum_time)) maximum
FROM (
SELECT
MAX(name) AS name,
SUM(TIME_TO_SEC(ending_time) - TIME_TO_SEC(starting_time)) sum_time
FROM working_hours wh, employees
WHERE wh.employees_id = employees.id
AND project_id IS NOT NULL
GROUP BY wh.employees_id
) x
group by x.name;
Simply use Order by LIMIT -
SELECT X1.name, X1.maximum
FROM (SELECT name, SUM(TIME_TO_SEC(ending_time) - TIME_TO_SEC(starting_time)) maximum
FROM working_hours wh, employees
WHERE wh.employees_id=employees.id
GROUP BY name) X1
JOIN (SELECT SUM(TIME_TO_SEC(ending_time) - TIME_TO_SEC(starting_time)) sum_time
FROM working_hours wh, employees
WHERE wh.employees_id=employees.id
AND project_id is not null
GROUP BY employees_id
ORDER BY sum_time DESC
LIMIT 1) X2 ON X2.sum_time = X1.maximum;

Counting distinct dates from two columns in a single SQL table

I've been reading through the solutions of similar problems posted here, but none seem to resolve my particular issue.
I currently have a table (CT_JOINED) that includes three columns: an identifer column (TUMOURID), a date column (AVCT_DATE) and another date column (OPDATE).
As an example, the columns for two IDs look as follows:
ID, AVCT_DATE, OPDATE
1, 06-APR-13, 06-APR-13
1, 06-APR-13, 14-JUN-13
1, 06-APR-13, 22-JUN-13
2, 03-APR-14, 10-DEC-15
2, 03-APR-14, 31-DEC-15
What I'm attempting to do is create a column that is equal to the number of unique dates per ID. So the result for ID 1 would be 3 and the result for ID 2 would be 3.
I have attempted a count of distinct values across the two columns, but this does not provide the answers above (it instead reports values of 3 and 2 respectively):
select TUMOURID, COUNT(DISTINCT(AVCT_DATE || OPDATE)) AS COUNT
FROM CT_JOINED
GROUP BY TUMOURID;
The same thing happens if I try and do the same in a new table:
CREATE TABLE CT_DISTINCT AS (
SELECT TUMOURID, COUNT(*) AS COUNT
FROM (
SELECT DISTINCT TUMOURID, AVCT_DATE, OPDATE
FROM CT_JOINED)
GROUP BY TUMOURID
);
I'm at a loss. Is it possible?
You could use:
SELECT TUMOURID, COUNT(DISTINCT d) AS cnt
FROM (select TUMOURID, AVCT_DATE AS d
FROM CT_JOINED
UNION ALL
SELECT TUMOURID, OPDATE AS d) sub
GROUP BY TUMOURID;
Unpivot the data and then use count(distinct) or remove duplicates along the way:
select tumourid, count(*)
from ((select tumourid, avct_date as dte
from ct_joined
) union -- intentional to remove duplicates
(select tumourid, opdate as dte
from ct_joined
)
) t
group by tumourid;
Use UNION to avoid duplicate date & just use count(*) :
SELECT tumourid, COUNT(date)
FROM ((SELECT tumourid, avct_date AS date
FROM ct_joined
) UNION
(SELECT tumourid, opdate
FROM ct_joined
)
) t
GROUP BY tumourid;
All of the answers below work like a charm with a few tweaks to also account for rows with null values. For instance:
SELECT TUMOURID, COUNT(*)
FROM ((SELECT TUMOURID, AVCT_DATE AS DTE
FROM CT_JOINED
WHERE AVCT_DATE IS NOT NULL
) UNION
(SELECT TUMOURID, OPDATE AS DTE
FROM CT_JOINED
WHERE OPDATE IS NOT NULL
)
) T
GROUP BY TUMOURID;
Many thanks.

How to get the ID of the max counted user in Order table

I have a table with
orderNumber(pk) , customerNumber , comment
I have to count the maximum order placed by a user and show its user ID and MAX count . I have following Query
It shows the count Right but it takes the first CustomerNumber in the table
SELECT maxCount.customerNumber , MAX(`counted`) FROM
(
SELECT customerNumber, COUNT(*) AS `counted`
FROM `orders`
GROUP BY `customerNumber`
)as maxCount
Thanks & regards
Just use ORDER BY with your inner query:
SELECT customerNumber, COUNT(*) AS `counted`
FROM `orders`
GROUP BY `customerNumber`
ORDER BY COUNT(*) DESC
LIMIT 1
If you want to return all customer numbers in the event of a tie, you can use a HAVING clause with a subquery which identifies the maximum count:
SELECT customerNumber, COUNT(*) AS counted
FROM orders
GROUP BY customerNumber
HAVING COUNT(*) = (SELECT MAX(t.counted) FROM (SELECT COUNT(*) AS counted
FROM orders
GROUP BY customerNumber) t)
Demo here:
SQLFiddle

making a query for stock/price trend in mysql

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

mysql 2 set of sum using groupby rollup

I have a query
select user_id,sum(hours),date, task_id from table where used_id = 'x' and date >='' and date<= '' group by user_id, date, task_id with roll up
The query works fine. But I also need to find a second sum(hours) where the group by order is changed.
select user_id,sum(hours),date, task_id from table where used_id = 'x' group by user_id,task_id
(The actual where condition is much longer.)
Is it possible to get both the sum in a single query since the where condition almost the same?
SELECT * FROM (
SELECT 1 AS list_id
, user_id
, sum(hours) AS total_hours
, `date`
, task_id
FROM table WHERE used_id = 'x' AND `date` BETWEEN #thisdate AND #thatdate
GROUP BY user_id, `date`, task_id /*WITH ROLLUP*/
UNION ALL
SELECT 2 AS list_id
, user_id
, sum(hours) AS total_hours
, `date`
, task_id
FROM table
WHERE used_id = 'x'
GROUP BY user_id,task_id WITH ROLLUP ) q
/*ORDER BY q.list_id, q.user_id, q.`date`, q.task_id*/
Depending on your needs, you should only need one with rollup, or two.