I have this query:
SELECT
count(*), `merchant_id`, `merchant_finance_id`, `merchant_channel_id`, `status`
FROM `application`
WHERE `created_at` >= '2018-04-30' AND `created_at` < '2018-05-01'
GROUP BY `merchant_id`, `merchant_finance_id`, `merchant_channel_id`, `status`
Which results in the following:
-------------------------------------------------------------------------------
| count(*) | merchant_id | merchant_finance_id | merchant_channel_id | status |
-------------------------------------------------------------------------------
| 2 | D8E2459CD78C | 55E4D520AC1C | 66A1861918C5 | ACCEPTED |
| 2 | D8E2459CD78C | 55E4D520AC1C | 66A1861918C5 | REFERRED |
| 1 | E50E50212627 | 6F8F15729DA7 | E02ACD64B452 | AWAITING-ACTIVATION |
| 2 | E50E50212627 | 6F8F15729DA7 | E02ACD64B452 | DEPOSIT-PAID |
| 1 | E50E50212627 | 6F8F15729DA7 | E02ACD64B452 | READY |
| 1 | E50E50212627 | 6F8F15729DA7 | E02ACD64B452 | REFERRED |
| 1 | F04FBD7AEB30 | C11CBD2FC1F8 | 21F2D435EA9D | AWAITING-ACTIVATION |
-------------------------------------------------------------------------------
But is there a way I can arranged the status into sub-columns instead? Eg:
-------------------------------------------------------------------------------
| count(*) | merchant_id | merchant_finance_id | merchant_channel_id | accepted | referred | awaiting_activation | deposit_paid | ready
-------------------------------------------------------------------------------
| 2 | D8E2459CD78C | 55E4D520AC1C | 66A1861918C5 | 2 | 2 | 0 | 0 | 0 |
| 5 | E50E50212627 | 6F8F15729DA7 | E02ACD64B452 | 0 | 1 | 1 | 2 | 1 |
| 1 | F04FBD7AEB30 | C11CBD2FC1F8 | 21F2D435EA9D | 0 | 0 | 1 | 0 | 0 |
-------------------------------------------------------------------------------
Note:
There is a defined list of different status types - so I don't have to worry about "BLAHBLAH" somehow being a status type.
You can try to use condition aggregate function, If you use Mysql you can do simplest like this.
SELECT
count(*),
`merchant_id`,
`merchant_finance_id`,
`merchant_channel_id`,
SUM(`status`='ACCEPTED'),
SUM(`status`='REFERRED'),
SUM(`status`='awaiting_activation'),
SUM(`status`='deposit_paid'),
SUM(`status`='READY')
FROM `application`
WHERE `created_at` >= '2018-04-30' AND `created_at` < '2018-05-01'
GROUP BY `merchant_id`, `merchant_finance_id`, `merchant_channel_id`
TestDLL
CREATE TABLE T(
merchant_id varchar(50),
merchant_finance_id varchar(50),
merchant_channel_id varchar(50),
`status` varchar(50)
);
INSERT INTO T VALUES ('D8E2459CD78C', '55E4D520AC1C','66A1861918C5' ,'ACCEPTED');
INSERT INTO T VALUES ('D8E2459CD78C', '55E4D520AC1C','66A1861918C5' ,'REFERRED');
INSERT INTO T VALUES ('E50E50212627', '6F8F15729DA7','E02ACD64B452' ,'AWAITING-ACTIVATION');
INSERT INTO T VALUES ('E50E50212627', '6F8F15729DA7','E02ACD64B452' ,'DEPOSIT-PAID');
INSERT INTO T VALUES ('E50E50212627', '6F8F15729DA7','E02ACD64B452' ,'READY');
INSERT INTO T VALUES ('E50E50212627', '6F8F15729DA7','E02ACD64B452' ,'REFERRED');
INSERT INTO T VALUES ('F04FBD7AEB30', 'C11CBD2FC1F8','21F2D435EA9D' ,'AWAITING-ACTIVATION');
Query 1:
SELECT
`merchant_id`,
`merchant_finance_id`,
`merchant_channel_id`,
SUM(`status`='accepted') accepted,
SUM(`status`='referred') referred,
SUM(`status`='awaiting_activation') awaiting_activation,
SUM(`status`='deposit_paid') deposit_paid,
SUM(`status`='ready') ready
FROM T
GROUP BY `merchant_id`, `merchant_finance_id`, `merchant_channel_id`
Results:
| merchant_id | merchant_finance_id | merchant_channel_id | accepted | referred | awaiting_activation | deposit_paid | ready |
|--------------|---------------------|---------------------|----------|----------|---------------------|--------------|-------|
| D8E2459CD78C | 55E4D520AC1C | 66A1861918C5 | 1 | 1 | 0 | 0 | 0 |
| E50E50212627 | 6F8F15729DA7 | E02ACD64B452 | 0 | 1 | 0 | 0 | 1 |
| F04FBD7AEB30 | C11CBD2FC1F8 | 21F2D435EA9D | 0 | 0 | 0 | 0 | 0 |
Related
I have a table like this:
+---------------+--------------+------+-----+----------+
| Field | Type | Null | Key | Default |
+---------------+--------------+------+-----+----------+
| id | smallint(6) | NO | PRI | NULL |
| Book | tinyint(4) | NO | | NULL |
| Chapter | smallint(6) | NO | | NULL |
| Paragraph | smallint(6) | NO | | NULL |
| Text | text | YES | | NULL |
| RevisionNum | mediumint(9) | NO | PRI | NULL |
+---------------+--------------+------+-----+----------+
mysql> select id,Book,Chapter,Paragraph,RevisionNum FROM MyTable ORDER BY id LIMIT 11;
+-----+------+---------+-----------+-------------+
| id | Book | Chapter | Paragraph | RevisionNum |
+-----+------+---------+-----------+-------------+
| 1 | 1 | 1 | 1 | 0 |
| 1 | 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 | 2 |
| 2 | 1 | 2 | 2 | 0 |
| 2 | 1 | 2 | 2 | 1 |
| 2 | 1 | 2 | 2 | 2 |
| 2 | 1 | 2 | 2 | 3 |
| 3 | 1 | 2 | 3 | 0 |
| 4 | 1 | 2 | 4 | 0 |
| 4 | 1 | 2 | 4 | 1 |
| 5 | 1 | 3 | 5 | 0 |
+-----+------+---------+-----------+-------------+
To find a book or chapter which has no unrevised paragraph,
I wish to query either the minimum value of the maximums of
all the distinct id's for that chapter or book, or else in
some fashion determine that no id remains unedited (with a
MAX(RevisionNum) of zero).
Most of my attempts to date have ended in errors like this one:
SELECT DISTINCT Book,RecordNum FROM MyTable
-> WHERE 0 < ALL (SELECT DISTINCT RecordNum,MAX(RevisionNum)
FROM MyTable
WHERE MAX(RevisionNum) > 0);
ERROR 1111 (HY000): Invalid use of group function
...And I wasn't using the "GROUP BY" function at all!
The following query produces results, but simply
gives ALL id's, and does not actually show a unique
set of Book records, as requested. How could this happen?
SELECT DISTINCT Book,id,MAX(RevisionNum) FROM MyTable GROUP BY id LIMIT 5;
+------+----+------------------+
| Book | id | MAX(RevisionNum) |
+------+----+------------------+
| 1 | 1 | 30 |
| 1 | 2 | 16 |
| 1 | 3 | 15 |
| 1 | 4 | 10 |
| 1 | 5 | 9 |
+------+----+------------------+
What would the correct query be to give results more like this:
+------+-----+-----------------------+
| Book | id | MIN(MAX(RevisionNum)) |
+------+-----+-----------------------+
| 1 | 5 | 3 |
| 2 | 17 | 1 |
| 3 | 33 | 2 |
| 4 | 147 | 0 |
| 5 | 225 | 2 |
+------+-----+-----------------------+
Are you looking for two levels of aggregation?
select id, book, min(max_revisionnum)
from (select id, book, chapter, paragraph, max(revisionnum) as max_revisionnum
from mytable
group by id, book, chapter, paragraph
) t
group by id, book;
EDIT:
Based on your comment, you can use:
select *
from (select id, book, chapter, paragraph, max(revisionnum) as max_revisionnum,
row_number() over (partition by book order by max(revisionnum) desc) as seqnum
from mytable
group by id, book, chapter, paragraph
) t
where seqnum = 1;
Here is a db<>fiddle.
In older versions of MariaDB, you can use a correlated subquery:
select t.*
from mytable t
where (id, book, chapter, paragraph, revisionnum) = (select t2.id, t2.book, t2.chapter, t2.paragraph, t2.revisionnum
from mytable t2
where t2.book = t.book
order by t2.revisionnum desc
limit 1
);
For this query, try adding an index on (book, revisionnum desc).
The table structure and data is present at https://www.db-fiddle.com/f/5rKXiavsoMeQazSHwxaTVK/0
i am trying to get the percentage of all previous date range.
circle_name`|current_capacity|2020-03-16|2020-03-17|2020-03-18|
where current capacity is the max date capacity and the percentage of each date in rows.
The final out like https://www.db-fiddle.com/f/wTFejVRzQBTXZkfWjBuqq8/0
select circle_name,Subscriber as current_capacity,
Subscriber/Subs_Capacity * 100 as percentage,
DATE_FORMAT(date,'%y-%m-%d') as date
from circle
where date BETWEEN date_add('2020-03-18',interval -3 day)
and '2020-03-18'
Please help here in pivot in mysql.
Here is one approach that uses conditional aggregation. Instead of assigning actual dates to column names (which would require dynamic SQL), this works by setting a variable that represents the date from which you want the computation to start, and then generates columns named d_2 (for day - 2), d_1 and d_0.
set #mydate = '2020-03-18';
select
circle_name,
max(case when date = #mydate then subscriber end) current_capacity,
100 * sum(case when date = #mydate - interval 2 day then subscriber end)
/ sum(case when date = #mydate - interval 2 day then subs_capacity end) d_2,
100 * sum(case when date = #mydate - interval 1 day then subscriber end)
/ sum(case when date = #mydate - interval 1 day then subs_capacity end) d_1,
100 * sum(case when date = #mydate then subscriber end)
/ sum(case when date = #mydate then subs_capacity end) d_0
from circle
group by circle_name;
In your db fiddle, the query yields:
| circle_name | current_capacity | d_2 | d_1 | d_0 |
| ----------- | ---------------- | ------- | ------- | ------- |
| AP | 758415 | 90.8422 | 91.1373 | 91.3753 |
| AS | 764976 | 83.461 | 83.2508 | 82.7001 |
| BH | 807447 | 84.5168 | 86.2083 | 85.8986 |
| CH | 785384 | 87.4384 | 87.2934 | 87.2649 |
| DL | 859161 | 85.9683 | 85.5766 | 85.9161 |
| GJ | 882817 | 85.6419 | 85.7533 | 86.1285 |
| HP | 203300 | 80.9292 | 80.9608 | 81.32 |
| HR | 255511 | 84.9163 | 85.1213 | 85.1703 |
| JK | 592271 | 84.244 | 84.2937 | 84.6101 |
| KK | 729628 | 88.0607 | 88.1499 | 87.907 |
| KL | 793872 | 80.0359 | 79.5544 | 79.3872 |
| KO | 847638 | 84.6341 | 84.6501 | 84.7638 |
| MB | 687501 | 87.8208 | 85.9449 | 85.9376 |
| MH | 886554 | 95.8487 | 95.6997 | 88.6554 |
| MP | 821474 | 83.1335 | 83.3047 | 83.8239 |
| NE | 824807 | 87.5708 | 87.5969 | 86.8218 |
| OR | 710822 | 84.5128 | 85.2319 | 83.6261 |
| PB | 194300 | 88.798 | 96.5235 | 97.15 |
| RJ | 840310 | 82.438 | 83.7309 | 84.031 |
| TN | 725307 | 90.8855 | 90.7334 | 90.6634 |
| UE | 903366 | 89.8577 | 90.0483 | 90.3366 |
| UW | 729154 | 98.9529 | 87.1339 | 87.8499 |
| WB | 0 | 0 | 0 | 0 |
I'm trying to group by a new columns here - one three counts.
It's a scenario where I want to see open, closed and plan orders for each date.
At the moment, with the code below I'm getting the results however I want to have a column with Main Date and count for each dates.
The results I am getting are as follows:
+------------+----------+------------+--------+------------+--------+
| Closed | ClosedNo | Open | OpenNo | Plan | PlanNo |
+------------+----------+------------+--------+------------+--------+
| NULL | 0 | NULL | 0 | 2018-10-22 | 3 |
| NULL | 0 | NULL | 0 | 2018-10-23 | 1 |
| NULL | 0 | NULL | 0 | 2018-10-24 | 1 |
| NULL | 0 | NULL | 0 | 2018-10-25 | 1 |
| NULL | 0 | 2018-10-25 | 1 | NULL | 0 |
| NULL | 0 | 2018-10-26 | 1 | NULL | 0 |
| NULL | 0 | 2018-10-27 | 2 | NULL | 0 |
| 2018-10-22 | 3 | NULL | 0 | NULL | 0 |
| 2018-10-23 | 1 | NULL | 0 | NULL | 0 |
| 2018-10-25 | 1 | NULL | 0 | NULL | 0 |
+------------+----------+------------+--------+------------+--------+
The desired results are:
Date ClosedNo OpenNo PlanNo
22/10/2018 3 3
23/10/2018 1 1
24/10/2018 1
25/10/2018 1 1 1
26/10/2018 1
27/10/2018 2
This is a code I use.
CREATE TABLE Orders
(Closed DATE,
Open DATE,
Plan DATE);
insert into Orders values ("2018-10-23",NULL,NULL);
insert into Orders values ("2018-10-22",NULL,NULL);
insert into Orders values ("2018-10-22",NULL,NULL);
insert into Orders values ("2018-10-22",NULL,NULL);
insert into Orders values (NULL,NULL,"2018-10-23");
insert into Orders values (NULL,NULL,"2018-10-22");
insert into Orders values (NULL,NULL,"2018-10-22");
insert into Orders values (NULL,NULL,"2018-10-22");
insert into Orders values (NULL,"2018-10-26",NULL);
insert into Orders values (NULL,"2018-10-27",NULL);
insert into Orders values (NULL,"2018-10-27",NULL);
insert into Orders values (NULL,"2018-10-25",NULL);
insert into Orders values (NULL,NULL,"2018-10-24");
insert into Orders values ("2018-10-25",NULL,NULL);
insert into Orders values (NULL,NULL,"2018-10-25");
SELECT
Closed
, COUNT(Closed) AS 'ClosedNo'
,Open
, COUNT(Open) AS 'OpenNo'
,Plan
, COUNT(Plan) AS 'PlanNo'
FROM
Orders
GROUP BY
Closed, Open, Plan;
Firstly, Open and Date are Keyword(s) in MySQL. You should really name your column to something else; or you will have to use backticks around it.
We can use Coalesce() function to get the Date. It will consider the first non-null value.
Using Count() aggregation function, we can count the non-null rows, for a Date group.
Try the following instead:
SELECT
COALESCE(Closed, `Open`, Plan) AS `Date`,
COUNT(Closed) AS ClosedNo,
COUNT(`Open`) AS OpenNo,
COUNT(Plan) AS PlanNo
FROM Orders
GROUP BY `Date`
RESULT
| Date | ClosedNo | OpenNo | PlanNo |
| ---------- | -------- | ------ | ------ |
| 2018-10-22 | 3 | 0 | 3 |
| 2018-10-23 | 1 | 0 | 1 |
| 2018-10-24 | 0 | 0 | 1 |
| 2018-10-25 | 1 | 1 | 1 |
| 2018-10-26 | 0 | 1 | 0 |
| 2018-10-27 | 0 | 2 | 0 |
View on DB Fiddle
I do not really know if this is possible to do this but I will expose my problem.
I have two tables cases and progress
cases
+----------+--------------+---------------------+---------+------+
| id_cases | name | date_surgery | archive | done |
+----------+--------------+---------------------+---------+------+
| 1 | Cranioplasty | 2016-02-01 00:00:00 | 1 | 0 |
| 2 | Cranioplasty | 2016-02-02 00:00:00 | 0 | 0 |
| 3 | Other | 2016-02-03 00:00:00 | 0 | 0 |
| 4 | Osteotomy | 2016-02-04 00:00:00 | 0 | 0 |
| 5 | Bone Tumor | 2016-02-05 00:00:00 | 1 | 1 |
+----------+--------------+---------------------+---------+------+
progress (which contains thousands of records)
+-------------+---------+---------+---------+
| id_progress | task_id | case_id | current |
+-------------+---------+---------+---------+
| 1 | 103006 | 1 | 0 |
| 2 | 103002 | 1 | 1 |
| 3 | 103003 | 1 | 1 |
| 4 | 201006 | 5 | 0 |
| 5 | 201007 | 5 | 1 |
| .... | ... | ... | ...|
+-------------+---------+---------+---------+
The link between the tables is cases.id_cases = progress.case_id
I want to select all cases with archive and done = 0. I also want to get some progress that are linked to this case
I tought about a condition to select a specific range of task_id related to the result of cases.name.
So basically I want this
SELECT id_cases, name, date_surgery, task_id, current
FROM cases
LEFT JOIN progress on progress.case_id = cases.id_cases
WHERE archive = 0 AND done = 0
But if name is Cranioplasty I just want progress.task_id that are equal to 103006, 103002 and 105002. For Bone Tumor I want 201006, 205003 and 207001. And this for each different name.
There is no logic between the id_cases and the task_id. I must hardcode this.
I tried differents things but none suceeded
SELECT id_Cases, name, date_surgery, task_id, current
from cases
left join progress on progress.case_id = cases.id_cases
where archive = 0 and done = 0
and case when name='Cranioplasty' then task_id=103006 and task_id=103002 else
case when name='Bone Tumor' then task_id=201006 else
case when name='Osteotomy' then task_id=301002 else
case when name='MBIO' then task_id=401006 end end end end
order by name, date_surgery
In fine I try to get this result (task_id is not important, I just want to result of current)
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
| case | name | date_surg | task_1 | 1_res | task_2 | 2_res | task_3 | 3_res |
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
| 1 | Cranioplasty | date | 103006 | 0 | 103002 | 0 | 105002 | 1 |
| 1 | Cranioplasty | date | 103006 | 1 | 103002 | 1 | 105002 | 0 |
| 1 | Cranioplasty | date | 103006 | 1 | 103002 | 0 | 105002 | 1 |
| 2 | Cranioplasty | date | 103006 | 0 | 103002 | 1 | 105002 | 0 |
| 2 | Cranioplasty | date | 103006 | 1 | 103002 | 0 | 105002 | 1 |
| 2 | Cranioplasty | date | 103006 | 0 | 103002 | 1 | 105002 | 1 |
| 3 | Bone Tumor | date | 201006 | 1 | 205003 | 0 | 205005 | 0 |
| 3 | Bone Tumor | date | 201006 | 0 | 205003 | 1 | 205005 | 1 |
| ... | | | | | | | | |
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
PS : I just put my table as an example to help understanding the problem. It does not includes all the records
I know that I can use temporary or virtual table but I wanted to know how to resolve this with only a query
Well, anyway its bad practice to hardcode this relations between name and task id. You need to store them in database or smthng. So you can join that table and do it in 1 query.
If you cant or dont want to its better to save them atleast to an array so you can dynamically generate query part with this conditions if its possible.
select
a.id_cases,
a.name,
b.task_id,
b.current
from
cases a
left join
progress b ON b.case_id = a.id_cases
where
a.archive = 0
and a.done = 0
and (
(b.task_id in (103006,103002,105002) and a.name = 'Cranioplasty')
OR (b.task_id in (201006,205003,207001) and a.name = 'Bone Tumor')
)
If you can use any language to generate this part
and (
(b.task_id in (103006,103002,105002) and a.name = 'Cranioplasty')
OR (b.task_id in (201006,205003,207001) and a.name = 'Bone Tumor')
)
Do it. For example in php
foreach($arRealtions as $name => $taskIDs)
{
$query .= '(b.task_id in ('.implode(',',$taskIDs).') and a.name = "'.$name.'")';
}
I have a table which I pull data from. This data has a date and a stock symbol. There can be multiple rows of data with the same date and different stock symbols. I need to update the table so that there is a running total for all rows with the same date. When a new date occurs the cumulative count re-sets to 1 and then resumes.
A typical query:
mysql> SELECT Sym 'sym' , fdate as 'FilledDate', TsTradeNum 'numT'
-> FROM trades_entered_b2
-> WHERE fDate >= '2009-08-03' AND fDate <= '2009-08-07'
-> LIMIT 10;
+------+------------+------+
| sym | FilledDate | numT |
+------+------------+------+
| WAT | 2009-08-03 | 0 |
| ALGN | 2009-08-04 | 0 |
| POT | 2009-08-05 | 0 |
| PTR | 2009-08-06 | 0 |
| SCHW | 2009-08-06 | 0 |
| FDO | 2009-08-07 | 0 |
| NBL | 2009-08-07 | 0 |
| RRC | 2009-08-07 | 0 |
| WAT | 2009-08-08 | 0 |
| COCO | 2009-08-08 | 0 |
+------+------------+------+
What I want:
+------+------------+------+
| sym | FilledDate | numT |
+------+------------+------+
| WAT | 2009-08-03 | 1 |
| ALGN | 2009-08-04 | 1 |
| POT | 2009-08-05 | 1 |
| PTR | 2009-08-06 | 1 |
| SCHW | 2009-08-06 | 2 |
| FDO | 2009-08-07 | 3 |
| NBL | 2009-08-07 | 4 |
| RRC | 2009-08-07 | 5 |
| WAT | 2009-08-08 | 1 |
| COCO | 2009-08-08 | 2 |
+------+------------+------+
What I need to do is update the TsTradeNum column with the correct values. I have tried to create a function and various queries all failed.
Any ideas? Thanks in advance
Could try below.The query will increment numT by 1 if the previous row date is same with current row, else it will reset numT to 1.
SELECT sym, FilledDate, numT
FROM(
SELECT sym, FilledDate,
#count:=CASE WHEN ( #date <> FilledDate) THEN 1
ELSE
#count+1
END AS numT,
#date:=FilledDate as dlset
FROM
(SELECT #count:= -1) s,
(SELECT #date:= -1) d,
(SELECT id, sym, FilledDate
FROM mytable3
ORDER BY FilledDate,sym desc
) t ) a