Get the maximum number of consecutive zeros SQL - mysql

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

Leave Histograms (Leave Pattern) generation in SQL

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.

How can I count distinct months names in a set of date values?

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);

get last completed (some condition) id while counting

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

MYSQL - apply a where clause to only some fields

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.

MySQL query to count non-null values in a single row

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