count existing buyer with mysql - mysql

i have table like this with mysql version 5.7
CREATE TABLE order_match (
ID INT,
user_id INT,
createdAt DATE,
status_id INT,
quantity INT
);
INSERT INTO order_match VALUES
(1, 12, '2020-01-01', 4, 1),
(2, 12, '2020-01-03', 7, 1),
(3, 12, '2020-01-06', 7, 2),
(4, 13, '2020-01-02', 5, 2),
(5, 13, '2020-01-03', 6, 1),
(6, 14, '2020-03-03', 8, 0.5),
(7, 13, '2020-03-04', 4, 1),
(8, 15, '2020-04-04', 7, 3),
(9, 14, '2020-03-02', 7, 2),
(10, 14, '2020-03-10', 5, 4),
(11, 13, '2020-04-10', 8, 3),
(12, 13, '2020-04-11', 8, 2),
(13, 16, '2020-04-15', 8, 3);
select * from order_match
order by createdAt;
the output just like this
+---------+---------+------------+-----------+----------+
| ID | user_id | createdAt | status_id | quantity |
+---------+---------+------------+-----------+----------+
| 1 | 12 | 2020-01-01 | 4 | 1 |
| 4 | 13 | 2020-01-02 | 5 | 2 |
| 2 | 12 | 2020-01-03 | 7 | 1 |
| 5 | 13 | 2020-01-03 | 6 | 1 |
| 3 | 12 | 2020-01-06 | 7 | 2 |
| 9 | 14 | 2020-03-02 | 7 | 2 |
| 6 | 14 | 2020-03-03 | 8 | 1 |
| 7 | 13 | 2020-03-04 | 4 | 1 |
| 10 | 14 | 2020-03-10 | 5 | 4 |
| 8 | 15 | 2020-04-04 | 7 | 3 |
| 11 | 13 | 2020-04-10 | 8 | 3 |
| 12 | 13 | 2020-04-11 | 8 | 2 |
| 13 | 16 | 2020-04-15 | 8 | 3 |
| 13 rows | | | | |
+---------+---------+------------+-----------+----------+
with ID as the id of transaction, user_id as the buyer who doing transaction, createdAt as the date transaction happen, status_id as the status of transaction (which 4, 5, 6, 8 as the approval transaction) and quantity as the amount of quantity of every transaction
this is the fiddle
so i want to find out the statistic of how many transaction, total amount of quantity, and total frequency of unique user between 2020-03-01 until 2020-04-01, unique user is the user who doing his first approval transaction before 2020-03-01 and at least doing 1 approval transaction in between 2020-03-01 until 2020-04-01, based on the table i made the expected result just like this
+------------+------------------+-----------------+
| count user | total_order (kg) | total_order (x) |
+------------+------------------+-----------------+
| 1 | 1 | 1 |
+------------+------------------+-----------------+
explanation : as we know the user who become unique user in between 2020-03-01 until 2020-04-01 are user_id 13, because he doing his first approval transaction on 2020-01-02 (before 2020-03-01) and then doing his approval transaction at least one time on 2020-03-01 until 2020-04-01, on time range, user_id 13 (count user) doing 1 transaction (total_order (x)) and the amount are 1 kg (total_order (kg )
i've doing this syntax
select
count(distinct om.user_id) as count,
sum(om.quantity) as total_order_kg,
count(om.id) as order_x
from (select count(xx.count_) as count_
from (select count(user_id) as count_ from order_match
where status_Id in (4, 5, 6, 8)
group by user_id
) xx
) x1,
(select user_id
from order_match
group by user_id
) yy,
order_match om
where yy.user_id = om.user_id and
status_id in (4, 5, 6, 8)
and om.createdAt < '2020-03-01'
and EXISTS (select 1 from order_match om2
where om.user_id = om2.user_id
and status_id in (4, 5, 6, 8)
and om2.createdAt >= '2020-03-01'
and om2.createdAt <= '2020-04-01');
but idk why the result like this
+------------+------------------+-----------------+
| count user | total_order (kg) | total_order (x) |
+------------+------------------+-----------------+
| 1 | 3 | 2 |
+------------+------------------+-----------------+
THE FIDDLE

-- separate users statistic
SELECT user_id,
SUM(quantity * (createdAt >= #start)) total_order_kg,
SUM(createdAt >= #start) order_x
FROM order_match
WHERE createdAt <= #finish
GROUP BY user_id
HAVING SUM(createdAt >= #start)
AND SUM(createdAt >= #start) < COUNT(createdAt);
-- overall statistic
SELECT COUNT(*) users_count,
SUM(order_kg) total_order_kg,
SUM(order_count) total_order_count
FROM ( SELECT user_id,
SUM(quantity * (createdAt >= #start)) order_kg,
SUM(createdAt >= #start) order_count
FROM order_match
WHERE createdAt <= #finish
GROUP BY user_id
HAVING SUM(createdAt >= #start)
AND SUM(createdAt >= #start) < COUNT(createdAt) ) totals;
fiddle

'why the result like this' - you are using comma joins so are starting from a cartesian product you can see what is happening if you substitute the aggregations for actual values for example
select
om.user_id,
om.quantity,
om.id,
x1.count_,
yy.user_id
from (select count(xx.count_) as count_
from (select count(user_id) as count_ from t
where status_Id in (4, 5, 6, 8)
group by user_id
) xx
) x1,
(select user_id
from t
group by user_id
) yy,
t om
where yy.user_id = om.user_id and
status_id in (4, 5, 6, 8)
and om.createdAt < '2020-03-01'
and EXISTS (select 1 from t om2
where om.user_id = om2.user_id
and status_id in (4, 5, 6, 8)
and om2.createdAt >= '2020-03-01'
and om2.createdAt <= '2020-04-01');
Where t is my table name and a copy of order_match.
If you run this query without the where clause then you get 65 rows returned, if you run it with the where clause but not the exists check you get 3 rows returned if you run it in it's entirety you get
---------+----------+------+--------+---------+
| user_id | quantity | id | count_ | user_id |
+---------+----------+------+--------+---------+
| 13 | 2 | 4 | 4 | 13 |
| 13 | 1 | 5 | 4 | 13 |
+---------+----------+------+--------+---------+
2 rows in set (0.002 sec)
Which when aggregated produces the result you get from your query.
NB group by without any aggregation functions is just wrong.

Related

Can't use having sum or having count mysql 5.7

Let's say I have a table like this
CREATE TABLE order_match(ID int(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
quantity decimal(10,2), createdAt date NOT NULL, order_status_id int(10) NOT NULL,
createdby int(11), code_order varchar(20) NOT NULL);
CREATE TABLE air_way_bills (id int(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
code_order varchar(30) NOT NULL, customer_regency varchar(30) NOT NULL);
insert into air_way_bills values
(1, 0001, 'KOTA DEPOK'),
(2, 0002, 'KOTA JAKARTA'),
(3, 0003, 'KOTA BOGOR'),
(4, 0004, 'KOTA BOGOR'),
(5, 0005, 'KOTA TANGERANG'),
(6, 0006, 'KOTA JAMBI'),
(7, 0007, 'KOTA BOGOR'),
(8, 0009, 'KOTA TANGERANG');
insert into order_match values
(1, 0.2, '2020-02-02', 6, 01, 0001),
(2, 1, '2020-02-03', 7, 02, 0002),
(3, 1.3, '2020-02-04', 7, 03, 0003),
(4, 1.4, '2020-02-08', 5, 08, 0004),
(5, 1.2, '2020-02-05', 8, 04, 0005),
(6, 1.4, '2020-03-01', 8, 05, 0006),
(7, 0.23, '2020-01-01', 8, 03, 0007),
(8, 2.3, '2020-02-07', 8, 04, 0009);
this is table order_match, the id with the primary key, quantity is the quantity of the transaction, createdAt are the date transaction, order_status_id is the status of the transaction (with order_status_id 7 are not approved transaction), createdby are the users, and code_order are the destination and connected with air_way_bills code_order column
+----+----------+------------+-----------------+-----------+------------+
| ID | quantity | createdAt | order_status_id | createdby | code_order |
+----+----------+------------+-----------------+-----------+------------+
| 1 | 0.20 | 2020-02-02 | 6 | 1 | 1 |
| 2 | 1.00 | 2020-02-03 | 7 | 2 | 2 |
| 3 | 1.30 | 2020-02-04 | 7 | 3 | 3 |
| 4 | 1.40 | 2020-02-08 | 5 | 8 | 4 |
| 5 | 1.20 | 2020-02-05 | 8 | 4 | 5 |
| 6 | 1.40 | 2020-03-01 | 8 | 5 | 6 |
| 7 | 0.23 | 2020-01-01 | 8 | 3 | 7 |
| 8 | 2.30 | 2020-02-07 | 8 | 4 | 9 |
+----+----------+------------+-----------------+-----------+------------+
this is air_way_bills table, with order_match.code_order = air_way_bills.code_order
+----+------------+------------------+
| id | code_order | customer_regency |
+----+------------+------------------+
| 1 | 1 | KOTA DEPOK |
| 2 | 2 | KOTA JAKARTA |
| 3 | 3 | KOTA BOGOR |
| 4 | 4 | KOTA BOGOR |
| 5 | 5 | KOTA TANGERANG |
| 6 | 6 | KOTA JAMBI |
| 7 | 7 | KOTA BOGOR |
| 8 | 9 | KOTA TANGERANG |
+----+------------+------------------+
i want to find out the new users (createdby) in range date '2020-02-03' until '2020-02-07' with approval transaction (order_status_id not in 7) and sort with in the destination. new users is the users where doing transaction in between the range date, but never doing transaction before the date range (on this case, before '2020-02-03')
i used this query
SELECT COALESCE(customer_regency, 'Total') AS `Destination`,
SUM(quantity) AS `Qty(kg)`,
round(SUM(quantity) / any_value(totalsum) * 100, 1) AS `Qty(%)`,
COUNT(a.id) AS `Jumlah Order`,
round(COUNT(a.id) / any_value(totalcount) * 100, 1) AS `Jumlah Order(%)`
FROM order_match a
/* 1 */ INNER JOIN air_way_bills b
/* 1 */ ON a.code_order = b.code_order
/* 2 */ INNER JOIN ( SELECT s1.createdby
FROM order_match s1
WHERE s1.order_status_Id in (4, 5, 6, 8)
GROUP BY s1.createdby
HAVING COUNT(s1.createdAt BETWEEN '2020-02-03' AND '2020-02-07') >= 1)
AND COUNT(s1.createdAt < '2020-02-03') = 0 ) clients
/* 2 */ ON a.createdby = clients.createdby
JOIN ( SELECT SUM(quantity) totalsum,
COUNT(id) totalcount
FROM order_match
/* 3 */ INNER JOIN ( SELECT s2.createdby
FROM order_match s2
WHERE s2.order_status_id in (4, 5, 6, 8)
GROUP BY s2.createdby
HAVING COUNT(s2.createdAt BETWEEN '2020-02-03' AND '2020-02-07') >= 1)
AND COUNT(s2.createdAt < '2020-02-03') = 0 ) clients
/* 3 */ ON order_match.createdby = clients.createdby
WHERE order_status_Id in (4, 5, 6, 8)) totals
WHERE a.order_status_Id in (4, 5, 6, 8)
GROUP BY customer_regency WITH ROLLUP;
but it says
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND COUNT(s1.createdAt < '2020-02-03') = 0 ) clients
/* 2 */ ON a.createdby = c' at line 15
expected results
+----------------+---------+--------+--------------+-----------------+
| Destination | Qty(kg) | Qty(%) | Count Order | Count Order(%) |
+----------------+---------+--------+--------------+-----------------+
| KOTA TANGERANG | 3.50 | 100 | 2 | 100 |
| Total | 3.50 | 100.0 | 2 | 100.0 |
+----------------+---------+--------+--------------+-----------------+
explanation : because users (Createdby) 4 are only fit with the condition (doing transaction in range date and never doing transaction before, and had approval transaction (order_status_id not in 7)
Please try the following query:
SELECT COALESCE(customer_regency, 'Total') AS `Destination`,
SUM(quantity) AS `Qty(kg)`,
round(SUM(quantity) / any_value(totalsum) * 100, 1) AS `Qty(%)`,
COUNT(a.id) AS `Jumlah Order`,
round(COUNT(a.id) / any_value(totalcount) * 100, 1) AS `Jumlah Order(%)`
FROM order_match a
/* 1 */ INNER JOIN air_way_bills b
/* 1 */ ON a.code_order = b.code_order
/* 2 */ INNER JOIN ( SELECT s1.createdby
FROM order_match s1
WHERE s1.order_status_Id in (4, 5, 6, 8)
GROUP BY s1.createdby
HAVING (SUM(case when createdAt >= '2020-02-03' AND createdAt <= '2020-02-07' then 1 else 0 end) >= 1)
AND SUM(case when createdAt < '2020-02-03' then 1 else 0 end) = 0 ) clients
/* 2 */ ON a.createdby = clients.createdby
JOIN ( SELECT SUM(quantity) totalsum,
COUNT(id) totalcount
FROM order_match
/* 3 */ INNER JOIN ( SELECT s2.createdby
FROM order_match s2
WHERE s2.order_status_id in (4, 5, 6, 8)
GROUP BY s2.createdby
HAVING SUM(case when createdAt >= '2020-02-03' AND createdAt <= '2020-02-07' then 1 else 0 end) >= 1
AND SUM(case when createdAt < '2020-02-03' then 1 else 0 end) = 0 ) clients
/* 3 */ ON order_match.createdby = clients.createdby
WHERE order_status_Id in (4, 5, 6, 8)) totals
WHERE a.order_status_Id in (4, 5, 6, 8)
GROUP BY customer_regency WITH ROLLUP;
remove redundant ) after COUNT(s1.createdAt BETWEEN '2020-02-03' AND '2020-02-07') >= 1)
change count to sum. their differences please refer to office doc
The COUNT(expression) returns the number of rows that do not contain
NULL values as the result of the expression.
The SUM() function is an aggregate function that allows you to
calculate the sum of values in a set. The syntax of the SUM() function
is as follows:

how to track score gains in mysql

I would like to display a players current score as well as how many points they have gained within a selected time frame.
I have 2 tables
skills table
+----+---------+---------------------+
| id | name | created_at |
+----+---------+---------------------+
| 1 | skill 1 | 2020-06-05 00:00:00 |
| 2 | skill 2 | 2020-06-05 00:00:00 |
| 3 | skill 3 | 2020-06-05 00:00:00 |
+----+---------+---------------------+
scores table
+----+-----------+----------+-------+---------------------+
| id | player_id | skill_id | score | created_at |
+----+-----------+----------+-------+---------------------+
| 1 | 1 | 1 | 5 | 2020-06-06 00:00:00 |
| 2 | 1 | 1 | 10 | 2020-07-06 00:00:00 |
| 3 | 1 | 2 | 1 | 2020-07-06 00:00:00 |
| 4 | 2 | 1 | 11 | 2020-07-06 00:00:00 |
| 5 | 1 | 1 | 13 | 2020-07-07 00:00:00 |
| 6 | 1 | 2 | 10 | 2020-07-07 00:00:00 |
| 7 | 2 | 1 | 12 | 2020-07-07 00:00:00 |
| 8 | 1 | 1 | 20 | 2020-07-08 00:00:00 |
| 9 | 1 | 2 | 15 | 2020-07-08 00:00:00 |
| 10 | 2 | 1 | 17 | 2020-07-08 00:00:00 |
+----+-----------+----------+-------+---------------------+
my expected results are:-
24 hour query
+-----------+---------+-------+------+
| player_id | name | score | gain |
+-----------+---------+-------+------+
| 1 | skill 1 | 20 | 7 |
| 1 | skill 2 | 15 | 5 |
+-----------+---------+-------+------+
7 day query
+-----------+---------+-------+------+
| player_id | name | score | gain |
+-----------+---------+-------+------+
| 1 | skill 1 | 20 | 10 |
| 1 | skill 2 | 15 | 14 |
+-----------+---------+-------+------+
31 day query
+-----------+---------+-------+------+
| player_id | name | score | gain |
+-----------+---------+-------+------+
| 1 | skill 1 | 20 | 15 |
| 1 | skill 2 | 15 | 14 |
+-----------+---------+-------+------+
so far I have the following, but all this does is return the last 2 records for each skill, I am struggling to calculate the gains and the different time frames
SELECT player_id, skill_id, name, score
FROM (SELECT player_id, skill_id, name, score,
#skill_count := IF(#current_skill = skill_id, #skill_count + 1, 1) AS skill_count,
#current_skill := skill_id
FROM skill_scores
INNER JOIN skills
ON skill_id = skills.id
WHERE player_id = 1
ORDER BY skill_id, score DESC
) counted
WHERE skill_count <= 2
I would like some help figuring out the query I need to build to get the desired results, or is it best to do this with php instead of in the db?
EDIT:-
MYSQL 8.0.20 dummy data id's are primary_key auto increment but I didnt ad that for simplicity:-
CREATE TABLE skills
(
id bigint,
name VARCHAR(80)
);
CREATE TABLE skill_scores
(
id bigint,
player_id bigint,
skill_id bigint,
score bigint,
created_at timestamp
);
INSERT INTO skills VALUES (1, 'skill 1');
INSERT INTO skills VALUES (2, 'skill 2');
INSERT INTO skills VALUES (3, 'skill 3');
INSERT INTO skill_scores VALUES (1, 1, 1 , 5, '2020-06-06 00:00:00');
INSERT INTO skill_scores VALUES (2, 1, 1 , 10, '2020-07-06 00:00:00');
INSERT INTO skill_scores VALUES (3, 1, 2 , 1, '2020-07-06 00:00:00');
INSERT INTO skill_scores VALUES (4, 2, 1 , 11, '2020-07-06 00:00:00');
INSERT INTO skill_scores VALUES (5, 1, 1 , 13, '2020-07-07 00:00:00');
INSERT INTO skill_scores VALUES (6, 1, 2 , 10, '2020-07-07 00:00:00');
INSERT INTO skill_scores VALUES (7, 2, 1 , 12, '2020-07-07 00:00:00');
INSERT INTO skill_scores VALUES (8, 1, 1 , 20, '2020-07-08 00:00:00');
INSERT INTO skill_scores VALUES (9, 1, 2 , 15, '2020-07-08 00:00:00');
INSERT INTO skill_scores VALUES (10, 2, 1 , 17, '2020-07-08 00:00:00');
WITH cte AS (
SELECT id, player_id, skill_id,
FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) score,
FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) - FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at ASC) gain,
ROW_NUMBER() OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) rn
FROM skill_scores
WHERE created_at BETWEEN #current_date - INTERVAL #interval DAY AND #current_date
)
SELECT cte.player_id, skills.name, cte.score, cte.gain
FROM cte
JOIN skills ON skills.id = cte.skill_id
WHERE rn = 1
ORDER BY player_id, name;
fiddle
Ps. I don't understand where gain=15 is taken for 31-day period - the difference between '2020-07-08 00:00:00' and '2020-06-06 00:00:00' is 32 days.
Well i think you need a (temporary) table for this. I will call it "player_skill_gains". Its basically the players skills ordered by created_at and with an auto_incremented id:
CREATE TABLE player_skill_gains
(`id` int PRIMARY KEY AUTO_INCREMENT NOT NULL
, `player_id` int
, skill_id int
, score int
, created_at date)
;
INSERT INTO player_skill_gains(player_id, skill_id, score, created_at)
SELECT player_skills.player_id AS player_id
, player_skills.skill_id
, SUM(player_skills.score) AS score
, player_skills.created_at
FROM player_skills
GROUP BY player_skills.id, player_skills.skill_id, player_skills.created_at
ORDER BY player_skills.player_id, player_skills.skill_id, player_skills.created_at ASC;
Using this table we can relatively easily select the last skill for each row (id-1). Using this we can calculate the gains:
SELECT player_skill_gains.player_id, skills.name, player_skill_gains.score
, player_skill_gains.score - IFNULL(bef.score,0) AS gain
, player_skill_gains.created_at
FROM player_skill_gains
INNER JOIN skills ON player_skill_gains.skill_id = skills.id
LEFT JOIN player_skill_gains AS bef ON (player_skill_gains.id - 1) = bef.id
AND player_skill_gains.player_id = bef.player_id
AND player_skill_gains.skill_id = bef.skill_id
For the different queries you want to have (24 hours, 7 days, etc.) you just have to specify the needed where-part for the query.
You can see all this in action here: http://sqlfiddle.com/#!9/1571a8/11/0

Relation Between 2 columns

In MYSQL there are 2 columns in table column A and column B and if in column A continuously comes one 10th time and in column B 11th time comes true(B can be 1 or 0 between these 10 times ) so I want that column id of B.
+----+---+---+
| id | A | B |
+----+---+---+
| 1 | 1 | 0 |
| 2 | 0 | 1 |
| 3 | 1 | 0 |
| 4 | 1 | 0 |
| 5 | 1 | 0 |
| 6 | 1 | 1 |
| 7 | 1 | 0 |
| 8 | 1 | 1 |
| 9 | 1 | 1 |
| 10 | 1 | 0 |
| 11 | 1 | 1 |
| 12 | 1 | 0 |
| 13 | 0 | 1 |
+----+---+---+
I need this (column B id) (Where Column A continuously come 1 (10 times) and Column B (11th id after contenious 10 time 1 in column A )
You could use a running total in a sub query to help you with this on versions prior to mysql 8.0
drop table if exists t;
create table t
(id int,A int,B int);
insert into t values
(1, 1 ,0),
(2, 0 ,1),
(3, 1 ,0),
(4, 1 ,0),
(5, 1 ,0),
(6, 1 ,1),
(7, 1 ,0),
(8, 1 ,1),
(9, 1 ,1),
(10, 1 ,0),
(11, 1 ,1),
(12, 1 ,0),
(13, 1 ,1),
(14, 1 ,1),
(15, 1 ,1),
(16, 0 ,1);
select t1.id,t1.a,t1.b
from
(
select t.*,
if(t.a = 1, #rt:=#rt+1,#rt:=0) rt
from t
cross join (select #rt:=0) r
order by t.id
) t1
where t1.rt >= 10;
+------+------+------+
| id | a | b |
+------+------+------+
| 12 | 1 | 0 |
| 13 | 1 | 1 |
| 14 | 1 | 1 |
| 15 | 1 | 1 |
+------+------+------+
4 rows in set (0.00 sec)
This is a complicated one. Using window functions available in MySQL 8.0, I would proceed in 3 steps:
first compute row numbers in the overall group and in groups of A values
then do a cumulative sum of A values within groups of consecutive A values (using the difference between the 2 above groups), while using LEAD() to recover the id and B value of the next record
finally, filter on the record whose cumulative SUM is 10 and whose next B value is 1; the id of the next record is what you are looking for
Query:
SELECT leadID id
FROM (
SELECT
id,
SUM(A) OVER(PARTITION BY rn1 - rn2 ORDER BY id) sm,
LEAD(id) OVER(ORDER BY id) leadID,
LEAD(B) OVER(ORDER BY id) leadB
FROM (
SELECT
id,
A,
B,
ROW_NUMBER() OVER(ORDER BY id) rn1,
ROW_NUMBER() OVER(PARTITION BY A ORDER BY id) rn2
FROM mytable
) x
) x
WHERE sm = 10 AND leadB = 1
This demo on DB Fiddle with your sample data yields:
| id |
| --- |
| 13 |

MySQL - calculate row total using a temporary column when select

I have a table (4 columns) like
CREATE TABLE IF NOT EXISTS `myTable` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`refer_id` int(12) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`groupType` int(12) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
I create a simple data
INSERT INTO `myTable` (`name`, `refer_id`, `groupType`) VALUES
('a', 1, 1),
('b', 2, 1),
('c', 3, 1),
('d', 4, 2),
('e', 4, 2),
('f', 4, 2),
('g', 7, 2),
('h', 7, 2),
('i', 5, 3),
('k', 5, 3),
('l', 6, 3);
I have 3 groupType. while groupType 1 and 3 is the same (can not group)
and groupType 2 (is group with same refer_id).
It looks like
id groupType group_field total
1 1 1 1
2 1 2 1
3 1 3 1
4 2 group_4 3
7 2 group_7 2
9 3 9 1
10 3 10 1
11 3 11 1
I'm using below query to do that (i think it looks good)
select id,
groupType,
IF(groupType != 2, #gf:=id, #gf:=CONCAT('group_',refer_id)) as group_field,
count(*) as total
from myTable
group by group_field
order by id asc
And I want to get total rows of above query(8 rows) by following, but it is not correct. How to do that? Thanks (I don't want union all)
select id,
groupType,
IF(groupType != 2, #gf:=id, #gf:=CONCAT('group_',refer_id)) as group_field,
count(*) as total,
CONCAT_WS('', 1) AS defaultValue,
SUM(defaultValue) as totalCount
from myTable
group by group_field
order by id asc
maybe something like ?
id groupType group_field total defaultValue totalCount
1 1 1 1 1 8
2 1 2 1 1 8
3 1 3 1 1 8
4 2 group_4 3 1 8
7 2 group_7 2 1 8
9 3 9 1 1 8
10 3 10 1 1 8
11 3 11 1 1 8
Try This
CREATE TABLE IF NOT EXISTS `myTable` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`refer_id` int(12) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`groupType` int(12) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
✓
INSERT INTO `myTable` (`name`, `refer_id`, `groupType`) VALUES
('a', 1, 1),
('b', 2, 1),
('c', 3, 1),
('d', 4, 2),
('e', 4, 2),
('f', 4, 2),
('g', 7, 2),
('h', 7, 2),
('i', 5, 3),
('k', 5, 3),
('l', 6, 3);
✓
select min(id) id,
groupType,
IF(groupType != 2, #gf:=id, #gf:=CONCAT('group_',refer_id)) as group_field,
count(*) as total,
count(*) over () as cnt
from myTable
group by groupType, group_field
order by id asc
id | groupType | group_field | total | cnt
-: | --------: | :---------- | ----: | --:
1 | 1 | 1 | 1 | 8
2 | 1 | 2 | 1 | 8
3 | 1 | 3 | 1 | 8
4 | 2 | group_4 | 3 | 8
7 | 2 | group_7 | 2 | 8
9 | 3 | 9 | 1 | 8
10 | 3 | 10 | 1 | 8
11 | 3 | 11 | 1 | 8
db<>fiddle here
For MySQl 5.5+
select min(id) id,
groupType,
IF(groupType != 2, #gf:=id, #gf:=CONCAT('group_',refer_id)) as group_field,
count(*) as total,
(select count(distinct IF(groupType != 2, #gf:=id, #gf:=CONCAT('group_',refer_id))) from myTable) cnt
from myTable
group by groupType, group_field
order by id asc
id | groupType | group_field | total | cnt
-: | --------: | :---------- | ----: | --:
1 | 1 | 1 | 1 | 8
2 | 1 | 2 | 1 | 8
3 | 1 | 3 | 1 | 8
4 | 2 | group_4 | 3 | 8
7 | 2 | group_7 | 2 | 8
9 | 3 | 9 | 1 | 8
10 | 3 | 10 | 1 | 8
11 | 3 | 11 | 1 | 8
db<>fiddle here

MySQL - count open items and getting dates from different table

Happy Friday All, I have something I can not get sorted. I have asked before for support and found it was the best thing I could do :) So, I want to calculate number of open items based on two dates, open and close. All the data will be counted in t2 and the dates will go from t1 (that stores a lot of dates and hence I use SELECT DISTINCT)
So, the tables are as follows:
CREATE TABLE t1
(
ID int (10),
Date1 date);
insert into T1 values
( 1, '2018-12-17'),
( 2, '2018-12-18'),
( 3, '2018-12-19'),
( 4, '2018-12-19'),
( 5, '2018-12-19'),
( 6, '2018-12-20'),
( 7, '2018-12-20'),
( 8, '2018-12-21'),
( 9, '2018-12-22'),
(10, '2018-12-23'),
(11, '2018-12-24'),
(12, '2018-12-25'),
(13, '2018-12-26'),
(14, '2018-12-27'),
(15, '2018-12-28');
CREATE TABLE t2
(
ID int (10),
Open_Date date,
Close_Date date);
insert into t2 values
( 1, '2018-12-17', '2018-12-18'),
( 2, '2018-12-18', '2018-12-18'),
( 3, '2018-12-18', '2018-12-18'),
( 4, '2018-12-19', '2018-12-20'),
( 5, '2018-12-19', '2018-12-21'),
( 6, '2018-12-20', '2018-12-22'),
( 7, '2018-12-20', '2018-12-22'),
( 8, '2018-12-21', '2018-12-25'),
( 9, '2018-12-22', '2018-12-26'),
(10, '2018-12-23', '2018-12-27');
This is the outcome I want:
+------------+------------+
| Date | Count_open |
+------------+------------+
| 17/12/2018 | 1 |
| 18/12/2018 | 3 |
| 19/12/2018 | 2 |
| 20/12/2018 | 3 |
| 21/12/2018 | 4 |
| 22/12/2018 | 4 |
| 23/12/2018 | 3 |
| 23/12/2018 | 0 |
| 25/12/2018 | 0 |
| 27/12/2018 | 0 |
| 27/12/2018 | 0 |
| 28/12/2018 | 0 |
+------------+------------+
I have a total black out with the code and need your help.
Maybe this is what you are looking for?
select
x.Date1 as 'Date',
count(distinct t2.id) as 'Count_open'
from (select distinct Date1 from t1) x
left join t2 on x.Date1 between t2.Open_Date and t2.Close_Date
group by x.Date1
order by x.Date1
Result:
Date Count_open
---------- ----------
2018-12-17 1
2018-12-18 3
2018-12-19 2
2018-12-20 4
2018-12-21 4
2018-12-22 4
2018-12-23 3
2018-12-24 3
2018-12-25 3
2018-12-26 2
2018-12-27 1
2018-12-28 0