Is there anybody who can help me with mysql query? - mysql

SELECT
(SELECT SUM(kwh) FROM energy_logger WHERE TIME >= '05:30:00' AND TIME < '18:30:00' GROUP BY Date) as daytime,
(SELECT SUM(kwh) FROM energy_logger WHERE TIME >= '18:30:00' AND TIME < '22:30:00' GROUP BY Date) as peaktime,
(SELECT SUM(kwh) FROM energy_logger WHERE TIME >= '22:30:00' OR TIME < '05:30:00' GROUP BY Date) offpeaktime,
Date
FROM energy_logger
GROUP BY Date
ORDER BY ID DESC
This is my query!
And I always have an issue of this, "Subquery returns more than 1 row".....

I think that you are looking for conditional aggregataion:
select
date,
sum(case when time '05:30:00' and time < '18:30:00' then kwh end) daytime,
sum(case when time '18:30:00' and time < '22:30:00' then kwh end) peaktime,
sum(case when time '22:30:00' or time < '05:30:00' then kwh end) offpeaktime
from energy_logger
group by date
order by date
This will give you, for each day, the sum of kwh over the 3 distinct time slots (daytime, peaktime, offpeaktime).

Related

How to get the data within the same day?

I'm doing a query to calculate the verified order within the same day. Regarding how to calculate, I can do it but to limit the time, can you help me?
For example: TIMESTAMPDIFF(HOUR, enddate, startdate) <= '24',
the time will be within 1 day, but it can be from one day to next day.
Then how can get the data within the same day?
My original query is:
SELECT COUNT(*),
1.0 * count(CASE WHEN TIMESTAMPDIFF(HOUR, `Created Datetime`, `Order Verification Date`) <= '2' THEN `BOB Sales Order Item` ELSE NULL END) / COUNT(`BOB Sales Order Item`) AS within_2hours_rate,
1.0 * count(CASE WHEN TIMESTAMPDIFF(DAY, `Created Datetime`, `Order Verification Date`) <= '24' THEN `BOB Sales Order Item` ELSE NULL END) / COUNT(`BOB Sales Order Item`) AS within_the_sameday_rate
FROM data.oms
WHERE `Created Datetime` BETWEEN '2017-10-29 00:00:00' AND '2017-11-04 23:59:59' AND `Order Verification Status` = 'finance_verified'
Thanks in advance!
If you're looking to check that the two times are on the same calendar day then you can do DATE(`Created Datetime`) = DATE(`Order Verification Date`).

SQL query summary issue

I'm new to SQL and trying to create a total summary of a working SQL query. It's listing the total results from one month of data.
Now I need the total values of the outcome of the query.
So I created a 'query in a query' piece of SQL, but it ain't working because my lack of SQL knowledge. I guess it's an easy fix for you pro's :-)
The working SQL query with the daily outcome of one month:
SELECT
DATE_FORMAT(date, '%d/%m/%y') AS Datum,
COUNT(*) AS Berichten,
SUM(CASE WHEN virusinfected>0 THEN 1 ELSE 0 END) AS Virus,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND isspam>0 THEN 1 ELSE 0 END) AS Ongewenst,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND (isspam=1) AND isrblspam>0 THEN 1 ELSE 0 END) AS RBL,
SUM(size) AS Grootte
FROM
maillog
WHERE
1=1
AND (1=1)
AND
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain1.nl'
OR
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain2.nl'
GROUP BY
Datum
ORDER BY
date
The incorrect query trying to create the monthly totals:
SELECT Datum,
SUM(Berichten) AS Berichten,
SUM(Virus) AS Virus,
SUM(Ongewenst) AS Ongewenst,
SUM(RBL) AS RBL,
SUM(Grootte) AS Grootte,
FROM ( SELECT
DATE_FORMAT(date, '%d/%m/%y') AS Datum,
COUNT(*) AS Berichten,
SUM(CASE WHEN virusinfected>0 THEN 1 ELSE 0 END) AS Virus,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND isspam>0 THEN 1 ELSE 0 END) AS Ongewenst,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND (isspam=1) AND isrblspam>0 THEN 1 ELSE 0 END) AS RBL,
SUM(size) AS Grootte
FROM
maillog
WHERE
1=1
AND (1=1)
AND
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain1.nl'
OR
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain2.nl'
GROUP BY
Datum
ORDER BY
date
) t
GROUP BY Datum;
Thanks in advance.
What you want can be done with just a little addition to your first SQL statement: add with rollup after the group by clause:
GROUP BY Datum WITH ROLLUP
It will run more efficiently than the version with sub-query, although it could work that way, but you should then remove the outer group by clause and not select Datum there, since you don't want the totals per date any more, but overall.
Still, you will lose the details and only get the overall totals then. You would have to use a union with your original query to get both levels of totals. You can imagine that the with rollup modifier will do the job more efficiently.

Get records with difference on 2 different date ranges in single query

I have sales table and have two different date ranges.
i.e, I have total sales between (2016-12-21 - 2016-12-30) is 100 and for period (2016-12-11 - 2016-12-20) is 85.
Now the result I want is
100 (sales of 2016-12-21 - 2016-12-30), 85 (sales of 2016-12-11 - 2016-12-20), 15 (difference of both periods) through single query.
What I am thinking is
select *, (a.sales - b.sales) as diff
from (select id, sum(sales) as sales from salestable where date >= '2016-12-21' and date <= '2016-12-30') a
join (select id, sum(sales) as sales from salestable where date >= '2016-12-11' and date <= '2016-12-20') b
on a.id = b.id;
Is there any other better way to do this?
You can use conditional aggregation:
select sum(case when date >= '2016-12-21' and date <= '2016-12-30' then sales else 0
end) as sales_a,
sum(case when date >= '2016-12-11' and date <= '2016-12-20' then sales else 0
end) as sales_b,
sum(case when date >= '2016-12-21' and date <= '2016-12-30'
then sales else 0
when date >= '2016-12-11' and date <= '2016-12-20'
then -sales
else 0
end) as sales_diff
from salestable;
If you want the overall sum by id (as suggested by your inclusion of id), then add id to the select and add group by id.
You can use case to do a conditional sum like this:
select id,
sum_21_to_30,
sum_11_to_20,
sum_21_to_30 - sum_11_to_20 diff
from (select id,
sum(case when date >= '2016-12-21' and date <= '2016-12-30' then sales else 0 end) sum_21_to_30,
sum(case when date >= '2016-12-11' and date <= '2016-12-20' then sales else 0 end) sum_11_to_20
from table group by id) t;

SELECT records using multiple critira

I have a table named all_data with fields date, value, and other fields.
I need to select last 7, 14, and 30 days from the database. There can be several entries with the same date like
date value
10-25-16 30
10-25-16 24
10-26-16 42
Here is the SELECT Statment I have that works for less than 30 days
$sql = "SELECT type_entry, COUNT(value) as val_count, FLOOR(SUM(value)) as sum_glu FROM all_data
WHERE DATEDIFF(NOW(), date) < 30 AND type_entry = 'Glucose'
ORDER BY date";
I want the same query 2 more times but changing the DATEDIFF statement with <14 and <7 so I end up with val_count1, val_count2, val_count3, sum_glu1, sum_glu2, sumglu3 I will use those to calculate the average of each.
I do not know enough SQL to figure out how to do it.
Here is a sample of readings
10/17/2016 116
10/17/2016 277
10/17/2016 145
10/18/2016 150
10/18/2016 125
10/19/2016 200
I need the number of records from 10/19/2016 for 7 days then I can do a weekly average of the readings.
You can use conditional aggregation here:
SELECT type_entry,
SUM(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN 1 ELSE 0 END) AS val_count_30,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN value ELSE 0 END)) AS sum_glu_30,
SUM(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN 1 ELSE 0 END) AS val_count_14,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN value ELSE 0 END)) AS sum_glu_14,
SUM(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN 1 ELSE 0 END) AS val_count_7,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN value ELSE 0 END)) AS sum_glu_7
FROM all_data
WHERE type_entry = 'Glucose'
ORDER BY date
If you just want the average of value for a 7 day period starting on 10/19/2016 for 7 days then you can just use a WHERE clause:
SELECT type_entry,
AVG(value) AS avgValue
FROM all_data
WHERE date BETWEEN '2016-10-19' AND DATE_ADD('2016-10-19', INTERVAL 7 DAY) AND
type_entry = 'Glucose'
GROUP BY type_entry
Basically you can retrieve all rows with criteria < 30 and all your following criterias contain within this one. You could add a CASE expression within aggregate functions to only perform aggregation within rows that match your criteria. All I did was changed the < X for every pair of columns:
SELECT
type_entry,
COUNT(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN value END) as val_count1,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN value END)) as sum_glu1,
COUNT(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN value END) as val_count2,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN value END)) as sum_glu2,
COUNT(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN value END) as val_count3,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN value END)) as sum_glu3
FROM all_data
WHERE DATEDIFF(NOW(), date) < 30 AND type_entry = 'Glucose'
GROUP BY type_entry
ORDER BY date
Also, note that I added the missing GROUP BY clause. Even though MySQL allows it, many different databases would yield an error. The recommended way is not to rely on MySQL mechanism in this matter.

Count number of entries in time interval 1 that appear in time interval 2 - SQL

I am new here and tried to look up the answer to my question but couldn't find anything on it. I am currently learning how to work with SQL queries and am wondering how I can count the amount of unique values that appear in two time intervals?
I have two columns; one is the timestamp while the other is a customer id. What I want to do is to check, for example, the amount of customers that appear in time interval A, let's say January 2014 - February 2014. I then want to see how many of these also appear in another time interval that i specify, for example February 2014-April 2014. If the total sample were 2 people who both bought something in january while only one of them bought something else before the end of April, the count would be 1.
I am a total beginner and tried the query below but it obviously won't return what I want because each entry only having one timestamp makes it not possible to be in two intervals.
SELECT
count(customer_id)
FROM db.table
WHERE time >= date('2014-01-01 00:00:00')
AND time < date('2014-02-01 00:00:00')
AND time >= date('2014-02-01 00:00:00')
AND time < date('2014-05-01 00:00:00')
;
Try this.
select count(distinct t.customer_id) from Table t
INNER JOIN Table t1 on t1.customer_id = t.customer_id
and t1.time >= '2014-01-01 00:00:00' and t1.time<'2014-02-01 00:00:00'
where t.time >='2014-02-01 00:00:00' and t.time<'2014-05-01 00:00:00'
Here's one method of doing this with conditional grouping in an inner-select.
Select Case
When GroupBy = 1 Then 'January - February 2014'
When GroupBy = 2 Then 'February - April 2014'
End As Period,
Count (Customer_Id) As Total
From
(
SELECT Customer_Id,
Case
When Time Between '2014-01-01' And '2014-02-01' Then 1
When Time Between '2014-02-01' And '2014-04-01' Then 2
Else -1
End As GroupBy
From db.Table
) D
Where GroupBy <> -1
Group By GroupBy
Edit: Sorry, misread the question. This will show you those that overlap those two time ranges:
Select Count(Customer_Id)
From db.Table t1
Where Exists
(
Select Customer_Id
From db.Table t2
Where t1.customer_id = t2.customer_id
And t2.Time Between '2014-02-01' And '2014-04-01'
)
And t1.Time Between '2014-01-01' And '2014-02-01'