I have a table named POIN and has a column which have comma separated values. I want to calculate each values on the comma separated. It's looks duplicate question because it has answered here. But I want to achieved this using single query instead of create a mysql function.
This is my table looks like :
id poin
------------------
1 1,5,9,3,5
2 2,4,8,5
3 4,7,9,1,5,7
Desired result :
id max min sum avg
--------------------------------------
1 1 9 23 4,6
2 8 2 19 4,75
3 9 1 33 5,5
Actually, I searched this in Google and this forum and didn't get a correct answer yet. I can't show what I have tried so far, because I have no clue where to start.
I don't know what application are you design, but I think it was bad design to store values in comma separated instead of create a table details. You can solved this without using a mysql function actually. First, you need to convert comma separated columns into rows and then you can do some calculation. This query may help you :
select id,max(val) as max,min(val) as min,sum(val) as sum,avg(val) as avg
from(
select id,(substring_index(substring_index(t.poin, ',', n.n), ',', -1)) val
from poin_dtl t cross join(
select a.n + b.n * 10 + 1 n
from
(select 0 as n 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) a,
(select 0 as n 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) b
order by n
) n <-- To make this simple, Create a table with one column that has 100 rows.
where n.n <= 1 + (length(t.poin) - length(replace(t.poin, ',', '')))
order by val asc
) as c_rows -- c_rows = convert comma separated columns into rows
group by id
The results should be like this:
id max min sum avg
--------------------------------------
1 1 9 23 4,6
2 8 2 19 4,75
3 9 1 33 5,5
Related
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
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
I have a database table containing project data with one record for each project. Below some sample data, duration is in months and is currently limited to max. 240, but can, theoretically, be infinite:
id name amount start_date duration
1 Project A 9.000 2013-06-24 3
2 Project B 5.000 2013-07-13 2
3 Project C 15.000 2013-08-06 3
Now I want MySQL to return the amount per month for each project: amount divided by duration for each month starting with the month the start_date is in. So based on the above data, MySQL will return something like below, ordered by month:
id name month amount_this_month
1 Project A 2013-06 3.000
1 Project A 2013-07 3.000
2 Project B 2013-07 2.500
1 Project A 2013-08 3.000
2 Project B 2013-08 2.500
3 Project C 2013-08 5.000
3 Project C 2013-09 5.000
3 Project C 2013-10 5.000
I saw something here for SQL Server, giving the suggestion to use a dummy table filled with numbers. Anyone has any ideas on how to do this without affecting the original database structure?
I need to do this in one query (so no temp (mem) tables).
How is this possible in MySQL? I saw some solutions for Oracle to iterate trough a (virtual) range/sequence, is it possible to do something like this in MySQL?
You can do something like this, joining a dummy range of numbers against itself to get the range of numbers, then adding that to the base month
SELECT id, name, DATE_FORMAT(DATE_ADD(start_date, INTERVAL Units.i + Tens.i * 10 + Hundreds.i * 100 MONTH), '%Y-%m') AS `month`, (amount / duration) AS `amount_this_month`
FROM SomeTable
CROSS JOIN (SELECT 0 AS i 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) Units
CROSS JOIN (SELECT 0 AS i 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) Tens
CROSS JOIN (SELECT 0 AS i 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) Hundreds
WHERE (Units.i + Tens.i * 10 + Hundreds.i * 100) < duration
I'm having difficulty creating a month->count select query in SQL.
Basically, I have a list of entries, all of which have a date associated with them. What I want the end result to be, is a list containing 12 rows (one for each month), and each row would contain the month number (1 for January, 2 for February, etc), and a count of how many entries had that month set as it's date. Something like this:
Month - Count
1 - 12
2 - 0
3 - 7
4 - 0
5 - 9
6 - 0
I can get an result containing months that have a count of higher than 0, but if the month contains no entries, the row isn't created. I get this result just by doing
SELECT Month(goalDate) as monthNumber, count(*) as monthCount
FROM goalsList
WHERE Year(goalDate) = 2012
GROUP BY Month(goalDate)
ORDER BY monthNumber
Thanks in advance for the help!
Try something like this,
SELECT a.monthNo, COUNT(b.goalDate)
FROM (
SELECT 1 monthNo UNION SELECT 2 monthNo
UNION
SELECT 3 monthNo UNION SELECT 4 monthNo
UNION
SELECT 5 monthNo UNION SELECT 6 monthNo
UNION
SELECT 7 monthNo UNION SELECT 8 monthNo
UNION
SELECT 9 monthNo UNION SELECT 10 monthNo
UNION
SELECT 11 monthNo UNION SELECT 12 monthNo
) a LEFT JOIN goalsList b
ON a.monthNo = CAST(month(b.goalDate) as SIGNED)
GROUP BY a.monthNo
ORDER BY a.monthNo;
The idea was to create a list of records for month number in a temporary table and joins it with the table against goalsList. (Assuming that the OP doesn't have a table for month numbers)
SQLFiddle Demo
Before anything else, here is the simplified schema (with dummy records) of the database:
ItemList
ItemID ItemName DateAcquired Cost MonthlyDep CurrentValue
================================================================================
1 Stuff Toy 2011-12-25 100.00 10.00 100.00
2 Mouse 2011-12-23 250.00 50.00 200.00
3 Keyboard 2011-12-17 250.00 30.00 190.00
4 Umbrella 2011-12-28 150.00 20.00 110.00
5 Aircon 2011-12-29 950.00 25.00 925.00
DepreciationTransaction
ItemID DateOfDep MonthlyDep
======================================
2 2012-01-31 250.00
3 2012-01-31 30.00
4 2012-01-31 20.00
5 2012-01-31 25.00
3 2012-02-29 30.00
4 2012-02-29 20.00
I need your suggestions to help me solve this problem. Basically I am creating a depreciation monitoring system of a certain LGU. The problem of the current database is that it lacks some records for a specific date of depreciation, for instance:
Lacking Records (this is not a table from the database)
ItemID LackingDate
============================
1 2012-01-31
1 2012-02-29
2 2012-02-29
5 2012-02-29
And because of the lacking records, I cannot generate the depreciation report for the month of MARCH. Any idea how can I insert missing records on the DepreciationTransaction?
What have I done so far? None. But a simple query that calculates the newly depreciated value (which produces incorrect value because of the missing records)
The problem here is that you will have to generate data. MySQL is not intended to generate data, you should do that at an application level and just tell MySQL to store it. In this case, the application should check wether there are missing records and create them if needed.
Leaving that aside, you can (awfully) create dynamic data with MySQL like this:
select il.itemId, endOfMonths.aDate from ((
select aDate from (
select #maxDate - interval (a.a+(10*b.a)+(100*c.a)+(1000*d.a)) day aDate 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) a, /*10 day range*/
(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) b, /*100 day range*/
(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) c, /*1000 day range*/
(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) d, /*10000 day range*/
(select #minDate := (select min(dateAcquired) from il),
#maxDate := '2012-03-01') e
) f
where aDate between #minDate and #maxDate and aDate = last_day(aDate)
) endOfMonths, il)
left join dt
on il.itemId = dt.itemId and endOfMonths.aDate = dt.dateOfDep
where dt.itemId is null and last_day(il.dateAcquired) < endOfMonths.aDate
Depending on the length of the date range you can reduce the amount of dynamically generated results (10000 days means over 27 years of records each representing one day) by removing tables (d, c, b and a) and removing them from the upper formula. Setting the #minDate and #maxDate variables will allow you to specify the dates between you want to filter the results. This dates should be the min date from which you have an item and the max date should be march, in your case.
In plain english: If select min(dateAcquired) from il returns a date before '2012-03-01' - 10000 days then you'll have to add another union.
Finally, just add the insert statement (if you really need to insert those records).
You may build a temporary table, which contains the date needed. And use the table to LEFT OUTER JOIN the "DepreciationTransaction" table.
SELECT dt.date_value, dt.itemid, ISNULL(SUM(dt.MonthlyDep), 0)
FROM tmp_date
LEFT OUTER JOIN
DepreciationTransaction AS dt
ON tmp_date.date_value = dt.DateOfDep
GROUP BY dt.date_value, dt.itemid
Of course, if your want that all of the items to be on report, you should make a cartesian product with tmp_date and items_id.