I have below table. The months columns represent the number of orders each customer has placed. I want to calculate the maximum number of consecutive zeros.
customer_id
Jan
Feb
Mar
Apr
May
Jun
1
1
2
1
1
2
1
2
1
0
0
0
0
0
3
0
0
1
0
0
0
4
0
0
0
1
0
1
so the result table would be:
customer_id
cons_zeros
1
0
2
5
3
3
4
3
I know there is a window function like that can tackle consecutive 0s for rows but am unsure how to do it for columns.
I would suggest unpivoting, treating this as a gaps-and-islands problem, and then reaggregating:
select customerid,
max(case when val = 0 then cnt else 0 end) as max_zeros
from (select customerid, val, (n - seqnum), count(*) as cnt
from (select cn.*,
row_number() over (partition by customerid, val order by n) as seqnum
from (select customerid, 1 as n, jan as val from t union all
select customerid, 2 as n, feb as val from t union all
select customerid, 3 as n, mar as val from t union all
select customerid, 4 as n, apr as val from t union all
select customerid, 5 as n, may as val from t union all
select customerid, 6 as n, jun as val from t
) cn
) cn
group by customerid, val, (n - seqnum)
) cn
group by customerid;
Related
In the Data shown,we need to do a continuous pattern check of Leaves,
for eg:
CASE
WHEN count("Leaves") BETWEEN 1 AND 2 THEN '1-2'
WHEN count("Leaves") BETWEEN 3 AND 5 THEN '3-5'
WHEN count("Leaves") >5 THEN '>5'
ELSE 'Above 5' END AS "Leave Occurence",
On Jan 1st and 2nd employee has taken 2 leaves togather which belongs to
'1-2'Bucket,
similarly 8,9,10,11th JAN it is contineous for 4 Days hence in '3-4'Bucket
and contineously more than 5 Leaves belongs to [<5]Bucket
Now we need the count of each Bucket for Month wise.
Here 1-2Bucket is 2
3-4Bucket is 1
<5 Bucket is also 1
We used this code ,but it gives the SUM,But not checking the contineous pattern
Year Month Leaves
2011 1-Jan 1
2-Jan 1
3-Jan 0
4-Jan 0
5-Jan 0
6-Jan 0
7-Jan 0
8-Jan 1
9-Jan 1
10-Jan 1
11-Jan 1
12-Jan 0
13-Jan 0
14-Jan 0
15-Jan 1
16-Jan 1
17-Jan 1
18-Jan 1
19-Jan 1
20-Jan 1
21-Jan 0
22-Jan 0
23-Jan 1
24-Jan 1
You can identify each group of leaves by counting the number of non-leaves before it. Then you have aggregation:
select min(date), max(date), count(*) as numdays
from (select t.*,
(select count(*)
from t t2
where t2.date <= t.date and t2.leave = 0
) as grp
from t
where t.leave = 1
) t
group by grp;
You can then format the results however you like. This gives you one row per continuous "leave" period.
I have table 'Data' and there has two field is Date_date1 and also Data_date2, and i want count it based on month.
this my database
Table: Data
Data_date1 Data_date2
---------------------------------
2019-07-23 2019-01-23
2019-08-23 2019-01-24
2019-08-24 2019-02-23
2019-09-21 2019-07-23
2019-09-22 2019-09-22
2019-09-23 2019-09-23
and i want the results like this one
Month Count_Date1 Count_Date2
Jan 0 2
Feb 0 1
July 1 1
Aug 2 0
Sep 3 9
Try this:
SELECT MONTH(data_date) m
,SUM(d=1) d1
,SUM(d=2) d2
FROM
(SELECT 1 d, data_date1 data_date FROM my_table
UNION
SELECT 2, data_date2 FROM my_table
) x
GROUP BY m
Here’s some setup with which to test this query, which produces the desired results:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(data_date1 DATE NOT NULL
,data_date2 DATE NOT NULL
);
INSERT INTO my_table VALUES
('2019-07-23','2019-01-23'),
('2019-08-23','2019-01-24'),
('2019-08-24','2019-02-23'),
('2019-09-21','2019-07-23'),
('2019-09-22','2019-09-22'),
('2019-09-23','2019-09-23');
You can use union all and group by:
select month(dte), sum(cnt1), sum(cnt2)
from ((select data_date1 as dte, 1 as cnt1, 0 as cnt2
from t
) union all
(select data_date2, 0, 1
from t
)
) dd
group by month(dte);
This shows the month number rather than the month name.
If you want the month name, you would do:
select monthname(dte), sum(cnt1), sum(cnt2)
from ((select data_date1 as dte, 1 as cnt1, 0 as cnt2
from t
) union all
(select data_date2, 0, 1
from t
)
) dd
group by monthname(dte), month(dte)
order by month(dte);
I'm trying to get the last completed task id of the child table while counting all the child records and completed child records:
set #tmp := 0;
select
count(*) total,
count(if(completed=1, 1, null)) completed,
#tmp:=if(completed=1, task_id, #tmp) last_completed_task_id
from child_table where parent_id = 6
order by sequence
Here is some sample data:
id parent_id completed task_id sequence
526 6 1 1 1
1653 6 0 5 2
2749 6 0 20 3
3840 6 0 21 4
4913 6 1 22 5
5983 6 0 23 6
7063 6 0 25 7
7183 6 0 26 8
8241 6 1 27 9
9317 6 0 28 10
10380 6 0 29 11
So final result should be like that:
total: 11
completed: 3
last_completed_task_id: 27
I know how to get it with separate queries, but I wish to get it with one query if possible.
You could use a cros join between the count and the max task_id eg:
select
count(*) total,
count(if(completed=1, 1, null)) completed,
t.last_completed_task_id
from child_table
cross join (
select max(task_id) last_completed_task_id
from child_table
where parent_id = 6
and completed=1 ) t
where parent_id = 6
You can easily get the last completed id using conditional aggregation:
select count(*),
sum(is_completed = 1),
max(case when is_completed = 1 then id end) as last_completed_id
from child_table ct
where parent_id = 6;
If task_id is increasing -- as in your sample data -- you can just use task_id rather than id in the max().
Otherwise, just join the table back in:
select cnt, cnt_completed, ct2.task_id
from (select count(*) as cnt,
sum(is_completed = 1) as cnt_completed,
max(case when is_completed = 1 then id end) as last_completed_id
from child_table ct
where parent_id = 6
) x join
child_table ct2
on x.last_completed_id = ct2.id
You could try this :
select count(*) total,
count(if(completed=1, 1, null)) completed,
(select task_id from child_table where parent_id = 6 and completed = 1 order by sequence desc limit 1) as last_completed_task_id
from child_table
where parent_id = 6
I have this table in MYSQL:
Year Type Value ID
0 0 5 1
2010 1 6 1
2011 1 4 1
2012 1 5 1
2013 1 7 1
2014 1 8 1
2015 1 5 1
0 0 6 2
2009 1 7 2
2010 1 4 2
2011 1 2 2
2012 1 8 2
2013 1 8 2
2014 1 5 2
I want to select the minimum and maximum year for each person (IDs 1 and 2), but I also want to select the value associated with type 0 for each person as well. Ideally this is what the query result would look like:
ID MinYear MaxYear Type0Value
1 2010 2015 5
2 2009 2014 6
The query should look, I think, something like this...
select ID,
(min(year) where type = 1) as MinYear,
(max(year) where type = 1) as MaxYear,
(value where type = 0) as Type0Value
from table
group by ID
But this is obviously not correct SQL syntax. How do I do this?
strange table structure, but:
select
_type0.id,
_type0.value,
_type1._min,
_type1._max
from
tbl as _type0
inner join (
select
id,
min(year) as _min,
max(year) as _max
from
tbl
where
1 = type
group by
id
) as _type1 on
_type0.id = _type1.id
where
0 = _type0.type;
you should use inner join.
one half will handle the min and max, second half the type0value:
select a.minYear, a.maxYear, a.id, b.type0value from
(select min(year) as minYear, max(year) as maxYear, id from table where id = 1 group by id) as a
inner join table as b on a.id = b.id
where b.type = 0
Your pseudo-code is actually pretty close. You just need conditional aggregation:
select ID,
min(case when type = 1 then year end) as MinYear,
max(case when type = 1 then year end) as MaxYear,
max(case when type = 0 then value end) as Type0Value
from table
group by ID;
If there could be multiple rows with type = 0, you might want group_concat() instead.
I'm trying to put together a MYSQL query that will count the number of Non-Null (or better yet, non-zero) values in select fields in a single row and then sort from lowest to highest (based on the count). For example, I have a table with 5 fields... ID, Name, Score_1, Score_2, Score_3. I want to count how many times the value "0" exists in Score_1, Score_2 and Score_3 for each record, then sort from most non zero values to least.
ID Name Score_1 Score_2 Score_3
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
4 Mike 4 5 5
I assume the query has to look something like this...
Select ID, Name, Score_1, Score_2, Score_3 where (???) ORDER BY (???)
Output should look like this (ID 4 is displayed first since it has the least amount of non-zero entries)...
ID Name Score_1 Score_2 Score_3
4 Mike 4 5 5
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
I'm somewhat new to mysql query's, so any help would be greatly appreciated. I thought the COUNT function would help, but that function appears to count columns from all rows. Perhaps there is a way to use the COUNT function and limit it to a singel row so it can be sorted by that row count?
This should do what you want:
SELECT ID, Name, Score_1, Score_2, Score_3
FROM Table1
ORDER BY (Score_1 = 0) + (Score_2 = 0) + (Score_3 = 0)
Result:
ID Name Score_1 Score_2 Score_3
4 Mike 4 5 5
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
try This:
Select id, Count1, Count2, Count3, Count4
From
(Select
Sum(Case When IsNull(Score_1,0) = 0 Then 1 Else 0 End) Count1,
Sum(Case When IsNull(Score_2,0) = 0 Then 1 Else 0 End) Count2,
Sum(Case When IsNull(Score_3,0) = 0 Then 1 Else 0 End) Count3,
Sum(Case When IsNull(Score_4,0) = 0 Then 1 Else 0 End) Count4
From Table
Group By Id) Z -- This column (Id) better not be the PK for this table!!!
Order By Count1 + Count2 + Count3 + Count4