MySQL include empty WEEKS data as 0 - mysql

is there way to include empty week value from empty result ? or how i can unionn empty missing weeks
there is bit of my query
SELECT
o.user_id , WEEK(FROM_UNIXTIME(o.cdate, '%Y-%m-%d'),7) as week_number,
FROM
(_orders AS `o`)
WHERE
o.cdate BETWEEN '1505409460' AND '1540815218'
GROUP BY
week_number
Result
1
2
4
6
8
requested result
1
2
3
4
5
6
7
8

This is just an example, there are numerous ways to achieve this. The first step is to have, or generate, a set on integers. Having a table of these is very handy actually. Here I use 2 subqueries cross joined to generate 100 rows (with n = 0 to 99)
select
ns.n, sq.*
from (
select
d1.digit + (d10.digit*10) as n
from (
SELECT 0 AS digit UNION ALL
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL
SELECT 9
) d1
cross join (
SELECT 0 AS digit UNION ALL
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL
SELECT 9
) d10
) ns
left join (
your query goes here
) sq on ns.n = sq.week_number
where n between 1 and 52
order by n

Related

Mysql query result generate months(1-12) for each category and arrange in same column order by category

I want to generate months no for 1-12 for each category. There are two categories, DEBIT and CREDIT. So, after finish print 1-12 for DEBIT. Then, it should go to next category and print the same with CREDIT in category column.
SELECT mon, #c:=#c+1 as cat_no, category
FROM
(
SELECT #m:=#m+1 as mon FROM
( SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION
SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12)a,
(SELECT #m:=0)c
)d,
(SELECT 'DEBIT' as category UNION SELECT 'CREDIT' as category)b,
(SELECT #c:=0)e
The fiddle here.
Result:
The result show the column category display two categories for each month before go to next. But, I expected to output all 1-12 before go to next month.
Expected:
Thank you.
SELECT mon.mon, cat.cat_no, cat.category
FROM ( SELECT 1 mon UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION
SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 ) AS mon
CROSS JOIN ( SELECT 1 cat_no, 'DEBIT' category UNION
SELECT 2, 'CREDIT' ) cat
ORDER BY cat_no, mon
https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=60416e7875ba7eb886e804c0bddbcadb

MySQL combining one query into another to use for Grafana

Im running an Openhab2 instance and collect data aswell as timestamps for important changes in datacollection. Inside my table item45 I store 2 colums Time and Value witch looks like this.
TABLE (item45) Design Screenshot 1 Screenshot 2
Time (datetime,primary) Value (datetime)
... ...
2018-10-17 03:08:30 2018-10-17 03:08:30
2018-10-19 00:13:13 2018-10-19 00:13:13
2018-10-19 00:27:58 2018-10-19 00:27:57
Its kind of the design of how Openhab stores data so nothing i can do about that.
i now try to use these values in Grafana just as ones like this:
Example of sucessful use
My Problem lies within Grafana im using to plot the querys. It disconnects the graphs if the next older point is outside the viewport. I tried to cope with that with virutally filling up the gaps in data inside the query. Like this:
Currently used Query
SELECT
1 as value,
'Net Reset' as metric,
UNIX_TIMESTAMP(v.gen_date) AS time_sec
from
(select DATE_SUB( FROM_UNIXTIME(1539707286), INTERVAL t3*1000 + t2*100 + t1*10 + t0 HOUR) gen_date from
(select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0
CROSS JOIN (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1
CROSS JOIN (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2
CROSS JOIN (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3
) v
LEFT JOIN item45
ON DATE_FORMAT( Time, '%Y-%m-%dT%H:00:00') = v.gen_date
where $__timeFilter(v.gen_date)
ORDER BY v.gen_date DESC;
AS u can see im using one of the given "hacks" here to generate hourly fillingdata just set to ones.
I need help to implement this query:
Query to replace FROM_UNIXTIME(...)
SELECT * FROM item45 ORDER BY Time DESC LIMIT 1
into the query 1 where FROM_UNIXTIME(1539707286) to set the actual stop of filling up the future data.
Im running MySQL57-server and currently cant upgrade to version 8 to use the with clause.
Desired Output
Time Value
2018-10-18 21:00:00 1 <- Inserted
2018-10-18 22:00:00 1 <- Inserted
2018-10-18 23:00:00 1 <- Inserted
2018-10-19 00:00:00 1 <- Inserted
2018-10-19 00:13:13 1
2018-10-19 00:27:58 1

Return 0 value record if record does not exist with unique id in Mysql

I have two tables, verified_users and cfw_documents. I wanted to show no of documents uploaded by each user in each month.
I tried below query-
SELECT a.user_id,count(distinct d.db_filename), MONTH(d.doc_date) as upload_month
FROM verified_users a
join cfw_documents d on a.user_id=d.user_id and d.doc_date >= a.created_on
GROUP BY 1,3 ORDER BY 1;
I got the output as :
user_ id count month
1 15 3
1 20 6
2 5 1
2 1 4
There are missing months for each user where user did not uploaded the records. I wanted to show such months with count 0.
Expected output:
user_ id count month
1 15 3
1 0 4
1 0 5
1 20 6
1 0 7
1 0 8
1 0 9
2 5 1
2 0 2
2 0 3
2 1 4
2 0 5
2 0 6
I tried to search but all solutions have only count and month columns but not other column from table.
Kindly suggest approach for this problem.
You should use a list for month and left join (or use a table for month number)
SELECT a.user_id, ifnull(count(distinct d.db_filename), 0), t.month as upload_month
FROM (
select 1 month from dual
union
select 2 from dual
union
select 3 from dual
union
select 4 from dual
union
select 5 from dual
union
select 6 from dual
union
select 7 from dual
union
select 8 from dual
union
select 9 from dual
union
select 10 from dual
union
select 11 from dual
union
select 12 from dual
) t
left join user_documents a on t.month = MONTH(d.doc_date)
join cfw_documents d on a.user_id=d.user_id and d.doc_date >= a.created_on
GROUP BY 1,3 ORDER BY 1;
looking to your sample seems you need result only for macthing month so you should use inner join
SELECT a.user_id, ifnull(count(distinct d.db_filename), 0), t.month as upload_month
FROM (
select 1 month from dual
union
select 2 from dual
union
select 3 from dual
union
select 4 from dual
union
select 5 from dual
union
select 6 from dual
union
select 7 from dual
union
select 8 from dual
union
select 9 from dual
union
select 10 from dual
union
select 11 from dual
union
select 12 from dual
) t
INNER join user_documents a on t.month = MONTH(d.doc_date)
INNER join cfw_documents d on a.user_id=d.user_id and d.doc_date >= a.created_on
GROUP BY 1,3 ORDER BY 1;

Finding Fifth Saturdays Mathematically?

So, where I work, my employees work alternating Saturdays: some employees are assigned to work the 1st and 3rd Saturdays of each month, some are assigned to work the 2nd and 4th Saturdays of each month.
One small problem arises: there are four months in the year which have five Saturdays. Which is easy enough to work around: 1st/3rd Employees work the 1st and 3rd Fifth Saturdays in the year and so on.
Some years have five months with fifth Saturdays, but we're not talking about that right now.
Anyway, to generate schedules for my employees, I first use the following code to generate a list of dates:
select
curdate() - interval (a.a + (10 * b.a) + (100 * c.a)) day as Date
from (
select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) as a
Then, I select the dates from the subquery, and join them to my Scheduling table to create a list of what each employee works on each date.
All of this works fine until Fifth Saturdays rear their ugly heads. At the moment, I use the following code to mathematically figure out which fifth saturday of the year it is:
mod(((datediff(date_add(a.date, interval (7-dayofweek(a.date)) day),date_add(subdate(a.Date,dayofyear(a.date-1)), interval (1-dayofweek(subdate(a.Date,dayofyear(a.date-1)))) day))+1)/7),4)
Or, to summarize, I find the number of days that have elapsed from the current first Sunday of the year to the current Saturday of this week, divide it by seven to figure out how many Saturdays have passed since then, and then find the modulo of 4 to figure out how many "extra" fifth Saturdays have passed since then.
...and this code will work perfectly fine unless the Fifth Saturday happens to fall on a week which is a multiple of four. Thankfully, that doesn't happen at all this year, but next year I'll need to figure out how to deal with this.
Is there a better way to mathematically figure out which fifth Saturday of the month a given fifth Saturday is?
Oh man. I was way overthinking the SQL piece of this. It was actually pretty easy. Create three temporary tables: one to hold the completed date table, one to hold all of the dates of interest in your period, and a third table specifically to find Fifth Saturdays:
drop temporary table if exists DATES;
create temporary table DATES (AdherenceDates date, WhichSaturday int,
WhichFifthSaturday int);
create temporary table DATES1 (AdherenceDates date, WhichSaturday int);
create temporary table DATES2 (FifthSaturdayDates date, WhichFifthSaturday
int auto_increment, primary key (WhichFifthSaturday));
insert into DATES1 (AdherenceDates, WhichSaturday)
select
a.Date as AdherenceDates,
case
when day(adddate(a.date,(7-dayofweek(a.date)))) <= 7
then 1
when day(adddate(a.date,(7-dayofweek(a.date)))) <= 14
then 2
when day(adddate(a.date,(7-dayofweek(a.date)))) <= 21
then 3
when day(adddate(a.date,(7-dayofweek(a.date)))) <= 28
then 4
when day(adddate(a.date,(7-dayofweek(a.date)))) > 28
then 5
end as WhichSaturday
from
(select
curdate() - interval (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) day
as Date
from (
select 0 as a union all select 1 union all select 2 union all select 3
union all select 4 union all select 5 union all select 6 union all select 7
union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union
all select 3 union all select 4 union all select 5 union all select 6 union
all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union
all select 3 union all select 4 union all select 5 union all select 6 union
all select 7 union all select 8 union all select 9) as c
cross join (select 0 as a union all select 1 union all select 2 union
all select 3 union all select 4 union all select 5 union all select 6 union
all select 7 union all select 8 union all select 9) as d
) as a
where dayofweek(a.Date) <> 1
and a.Date >= '2017-01-01'
order by a.Date asc
;
insert into DATES2 (FifthSaturdayDates)
select
a.Date as AdherenceDates
from
(select
curdate() - interval (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) day
as Date
from (
select 0 as a union all select 1 union all select 2 union all select 3
union all select 4 union all select 5 union all select 6 union all select 7
union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union
all select 3 union all select 4 union all select 5 union all select 6 union
all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union
all select 3 union all select 4 union all select 5 union all select 6 union
all select 7 union all select 8 union all select 9) as c
cross join (select 0 as a union all select 1 union all select 2 union
all select 3 union all select 4 union all select 5 union all select 6 union
all select 7 union all select 8 union all select 9) as d
) as a
where dayofweek(a.Date) = 7
and a.Date >= '2017-01-01'
and day(a.Date) > 28
order by a.date asc;
insert into DATES (AdherenceDates, WhichSaturday, WhichFifthSaturday)
select
DATES1.AdherenceDates,
DATES1.WhichSaturday,
DATES2.WhichFifthSaturday
from
DATES1
left join
DATES2
on DATES1.AdherenceDates = DATES2.FifthSaturdayDates;
drop temporary tables DATES1, DATES2;
select * from DATES
order by AdherenceDates asc;

Finding hourly passenger loads given boarding and deboarding time

I have the following table of transport records for a bus company:
CREATE TABLE ride_txn(
passenger_no int(11) pk,
txn_time timestamp,
action varchar(10)
)
where the action could be "Board" or "Deboard".
Say I have 2 rows where for passenger_no. 100, he boarded at 1.30pm and alighted at 4.30pm.
passenger_no txn_time action
100 13:30:00 Board
100 16:30:00 Deboard
Can I write an sql query to retrieve the hours that he is in the bus? I do the count at the beginning of each hour so he was in the bus at 2pm, 3pm and 4pm. In other words, I am trying to get something like
passenger_no hour_in_bus
100 2
100 3
100 4
Here's a start:
select
passenger_no, hr
from
ride_txn rt,
(
select 0 hr union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9 union all select 10 union all select 11 union all
select 12 union all select 13 union all select 14 union all
select 15 union all select 16 union all select 17 union all
select 18 union all select 19 union all select 20 union all
select 21 union all select 22 union all select 23
) hrs
where
action = 'Board' and
hrs.hr between
hour(txn_time) /* could add 3599 seconds to only count top of the hour */
and
(
select min(txt_time) from ride_txn rt2
where
rt2.passenger_no = rt.passenger_no
and rt2.txt_time > rt.txt_time and action = 'Deboard'
)
I had to assume that the events will pair off correctly and also that the "deboard" time will be greater than the "board" time. So nothing spans midnight and it takes place within a single day. It would handle multiple pairs within the day though.
I'm not sure if hour() is actually a MySQL function but I'm sure you can find the equivalent one. I'm also assuming it returns a number from 0 to 23.
select id,y.tm from
(
select id,
max(case when action = 'Deboard' then hour(dt) end) as d_time,
max(case when action = 'Board' then hour(dt) end) as b_time
from tablename
group by id) x
join
(
select distinct hour(dt) as tm from tablename
) y
on y.tm between x.b_time and x.d_time
This would work assuming you have all the 24 hours in the table.
with cte as (select a.passenger_no,case when minute(a.txn_time) > 0 or Second(a.txn_time) > 0 then hour(a.txn_time) + 1 else hour(a.txn_time) end as brd_time,
hour(b.txn_time) debrd_time,
from ride_txn a inner join ride_txn b
on a.passenger_no = b.passenger_no where a.action = 'Board' and b.action = 'DeBoard')
select
passenger_no, hr_12
from
cte,
(
select 0 hr, 0 hr_12 union all select 1,1 union all select 2,2 union all
select 3,3 union all select 4,4 union all select 5,5 union all
select 6,6 union all select 7,7 union all select 8,8 union all
select 9,9 union all select 10,10 union all select 11,11 union all
select 12,12 union all select 13,1 union all select 14,2 union all
select 15,3 union all select 16,4 union all select 17,5 union all
select 18,6 union all select 19,7 union all select 20,8 union all
select 21,9 union all select 22,10 union all select 23,11
) hrs
where
hrs.hr between brd_time and debrd_time