Empty rows for MySQL Query but using a WHERE - mysql

I have a table names lcMovimientos and what I need is a query where I get as a result the sum of the quantity of cantidadMovimientos but I want each row to be by the day of the week and only to sum the days of the current week, so after researching I found the best way to do this was creating a new table with the days of the week, so I now have a table called diasSemana
SELECT * FROM diasSemana
+-----------+
| diaSemana |
+-----------+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+-----------+
and a table called lcMovimientos
mysql> DESCRIBE lcMovimientos;
+-----------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+---------------+------+-----+---------+----------------+
| idMovimiento | int(11) | NO | PRI | NULL | auto_increment |
| idUsuario | int(11) | YES | | NULL | |
| tipoMovimiento | tinyint(4) | YES | | NULL | |
| cantidadMovimiento | decimal(20,2) | YES | | NULL | |
| idCategoria | int(11) | YES | | NULL | |
| fechaMovimiento | date | YES | | NULL | |
| idCuenta | int(11) | YES | | NULL | |
| descripcionMovimiento | varchar(255) | YES | | NULL | |
| etiquetasMovimiento | varchar(255) | YES | | NULL | |
+-----------------------+---------------+------+-----+---------+----------------+
I can make a query where I do get the sum of the cantidadMovimiento but when I add the where clause so I only get results from the current week, I no longer get the rows by day fo the week, so here is my query:
mysql> SELECT SUM( cantidadMovimiento ) , diaSemana, fechaMovimiento -> FROM diasSemana
-> LEFT JOIN lcMovimientos ON diaSemana = WEEKDAY( fechaMovimiento )
-> GROUP BY diaSemana;
+---------------------------+-----------+-----------------+
| SUM( cantidadMovimiento ) | diaSemana | fechaMovimiento |
+---------------------------+-----------+-----------------+
| 280.00 | 0 | 2012-02-20 |
| 800.00 | 1 | 2012-02-21 |
| 7000.00 | 2 | 2012-02-29 |
| NULL | 3 | NULL |
| NULL | 4 | NULL |
| -3300.78 | 5 | 2012-02-18 |
| 600.00 | 6 | 2012-02-26 |
+---------------------------+-----------+-----------------+
and when I use the WHERE clause:
mysql> SELECT SUM( cantidadMovimiento ) , diaSemana, fechaMovimiento
-> FROM diasSemana
-> LEFT JOIN lcMovimientos ON diaSemana = WEEKDAY( fechaMovimiento )
-> WHERE WEEK( fechaMovimiento, 1 ) = WEEK( CURRENT_DATE, 1 )
-> GROUP BY diaSemana;
+---------------------------+-----------+-----------------+
| SUM( cantidadMovimiento ) | diaSemana | fechaMovimiento |
+---------------------------+-----------+-----------------+
| 265.00 | 0 | 2012-02-20 |
| 800.00 | 1 | 2012-02-21 |
| 600.00 | 6 | 2012-02-26 |
+---------------------------+-----------+-----------------+
So my question is how can i make a query where I will get the results by the day of the week using the where to only get dates of the current week??? thank you so much in advance!

try this
SELECT
COALESCE(SUM( cantidadMovimiento ),0) AS cantidadMovimiento,
diaSemana,
DATE_ADD(DATE(NOW()), INTERVAL diaSemana-WEEKDAY(NOW()) DAY) AS weekday
FROM diasSemana
LEFT JOIN lcMovimientos
ON diaSemana = WEEKDAY( fechaMovimiento )
AND WEEK(fechaMovimiento) = WEEK(NOW()) AND YEAR(fechaMovimiento) = YEAR(NOW())
GROUP BY diaSemana;

Related

sql query to get products with season prices with discount

I have season table with this
+----+------------+------------+------------+-------+------+----------+------------+------------+------------+
| id | base_price | startDate | endDate | cost | type | Duration | product_id | created_at | updated_at |
+----+------------+------------+------------+-------+------+----------+------------+------------+------------+
| 1 | 100.00 | 1537390800 | 1538773200 | 95.00 | day | 2 | 9 | NULL | NULL |
| 2 | 100.00 | 1537390800 | 1538773200 | 85.00 | day | 3 | 9 | NULL | NULL |
| 3 | 100.00 | 1537390800 | 1538773200 | 75.00 | day | 4 | 9 | NULL | NULL |
| 4 | 100.00 | 1537390800 | 1538773200 | 70.00 | day | 5 | 9 | NULL | NULL |
+----+------------+------------+------------+-------+------+----------+------------+------------+------------+
and product table
+----+----------------------------+-----------+-----+-------+---------+--------------+---------------------+---------------------+---------------------+
| id | alias | status | img | price | user_id | published_at | deleted_at | created_at
| updated_at |
+----+----------------------------+-----------+-----+-------+---------+--------------+---------------------+---------------------+---------------------+
| 8 | toyota-corolla-1-6-elegant | draft | 18 | 30 | 1 | 2018-08-14 | NULL | 2018-08-14 15:06:12 | 2018-08-20 14:58:18 |
| 9 | test | published | | 0 | 1 | 2018-08-23 | 2018-09-10 19:44:29 | 2018-08-23 14:45:18 | 2018-09-10 19:44:29 |
+----+----------------------------+-----------+-----+-------+-------
Now I try this sql
SELECT *
FROM products,
(SELECT *
FROM season
WHERE Duration = ( SELECT MAX(Duration) FROM ec_season WHERE `Duration` <= 3)
) as t1
LEFT OUTER JOIN t1
ON t1.product_id = products.id
but it give me
1146 - The table '****.t1' does not exist
how to attach products to t1?
try this: Your join syntax is incorrect
SELECT *
FROM products left outer join
(SELECT *
FROM season
WHERE Duration = ( SELECT MAX(Duration) FROM ec_season WHERE `Duration` <= 3)
) as t1 ON t1.product_id = products.id

Could any one help me to make my query more efficient?

Could any one help me to make my query more efficient?
I'm a beginner of SQL,
as I know for efficient is to use index or primary key to let the B-tree search faster,therefore,I've already set the primary key for rid and index for (Date, Time)
However, my query is still too inefficient to output the result.
I'm trying to find the sensor(sid) which has the largest interval on '2017-03-04'.
Here is my code:
select tmp4.sid as largest_ivl_sensor
from
(
select tmp3.sid, MAX(tmp3.Dif) as max_for_each
from
(
select tmp1.sid, MIN(TIME_TO_SEC(DATE_SUB(tmp2.Time, INTERVAL tmp1.Time HOUR_SECOND))) as Dif
from
(
select se.sid, r.rid, r.Time
from (select rr.rid, rr.Time from records rr where rr.Date = '2017-03-04') as r, send se
where se.rid = r.rid
order by se.sid
) as tmp1
INNER JOIN
(
select se2.sid, r2.rid, r2.Time
from (select rr2.rid, rr2.Time from records rr2 where rr2.Date = '2017-03-04') as r2, send se2
where se2.rid = r2.rid
order by se2.sid
) as tmp2 ON tmp1.sid = tmp2.sid and TIME_TO_SEC(tmp1.Time) <= TIME_TO_SEC(tmp2.Time) and tmp1.rid <> tmp2.rid
GROUP BY tmp1.sid, tmp1.Time
) as tmp3
GROUP BY tmp3.sid
) as tmp4
group by tmp4.max_for_each
having tmp4.max_for_each = MAX(tmp4.max_for_each);
And here is the schema:
records
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| rid | int(11) | NO | PRI | NULL | |
| Date | date | YES | MUL | NULL | |
| Time | time | YES | | NULL | |
| Humidity | double(5,2) | YES | | NULL | |
| Temperature | double(5,2) | YES | | NULL | |
| PM1 | int(11) | YES | | NULL | |
| PM10 | int(11) | YES | | NULL | |
| PM25 | int(11) | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
send
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| sid | varchar(30) | NO | | NULL | |
| rid | int(11) | NO | PRI | NULL | |
+-------+-------------+------+-----+---------+-------+
Here is a example:
| rid |sid | Time |
| 1 | a | 00:00:00 |
| 2 | a | 00:01:00 |
| 3 | b | 00:05:00 |
| 4 | b | 00:07:00 |
| 5 | b | 00:11:00 |
| 6 | c | 00:00:00 |
| 7 | c | 00:03:00 |
| 8 | c | 00:04:00 |
desired result:
| sid|
| b|
Since it has largest interval 4 minutes
Another example:
| rid |sid | Time |
| 1 | a | 00:00:00 |
| 2 | b | 00:11:00 |
| 3 | c | 00:04:00 |
| 4 | b | 00:07:00 |
| 5 | a | 00:01:00 |
| 6 | c | 00:00:00 |
| 7 | c | 00:03:00 |
| 8 | b | 00:05:00 |
Thanks for helping me.
You could make use of variables in your SQL to keep track of the differences on-the-fly. Also, order by in combination with limit 1 is handy for getting the record with the highest value:
select sid,
max(diff) as max_diff
from (
select if(sid = #s, secs - #t, null) as diff,
#t := secs as secs,
#s := sid as sid
from (select sid,
time_to_sec(time) as secs
from records
inner join send on send.rid = records.rid
where date = '2017-03-04'
order by sid, time
) ordered
cross join (select #s := null, #t := null) init
) data
group by sid
order by max_diff desc
limit 1;
See it run on rextester.com.

Count how many entries are in a database at 5 minute intervals

I have multiple Raspberry Pi's collecting wifi beacons from mobile devices and save them in a mySQL DB. I have created a view in the DB. Each entry in the DB has the mobile device mac address, the pi id, rssi, location and a timestamp
I have created a view from multiple tables that looks like this.
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| pi_id | varchar(64) | NO | | NULL | |
| name | varchar(127) | NO | | NULL | |
| location | varchar(255) | NO | | NULL | |
| mac_id | varchar(200) | NO | | NULL | |
| rssi | int(11) | NO | | NULL | |
| datetime | datetime | NO | | NULL | |
+----------+--------------+------+-----+---------+-------+
For each Pi/location I want to count how many packets/beacons were seen during each 5 minute interval. I have been trying something like this.
SELECT datetime , location, count(*)
FROM packet_locations
GROUP BY DATE(DATE_SUB(datetime, INTERVAL 5 MINUTE)), location;
I want output like this:
+---------------------+----------+----------+
| datetime | location | count(*) |
+---------------------+----------+----------+
| 2016-01-26 00:00:00 | Pi1 | 44 |
| 2016-01-26 00:00:00 | Pi2 | 66 |
| 2016-01-26 00:05:00 | Pi1 | 100 |
| 2016-01-26 00:05:00 | Pi2 | 101 |
| 2016-01-26 00:10:00 | Pi1 | 128 |
| 2016-01-26 00:10:00 | Pi2 | 128 |
+---------------------+----------+----------+
SELECT concat( date_format(datetime,'%Y-%m-%d %k:')
, lpad(floor(minute(datetime)/5)*5,2,'0')
, ':00'
) datetime
, location
, count(1)
FROM packet_locations
GROUP BY date(datetime)
, hour(datetime)
, floor(minute(datetime)/5)
, location

MySQL - Average % value from last day insertions

I've got a table in MySQL:
+-----------------+-------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------------------+-------+
| period_duration | datetime | NO | PRI | 0000-00-00 00:00:00 | |
| duration | varchar(6) | YES | | NULL | |
| sample | varchar(2) | YES | | NULL | |
| corner | varchar(10) | YES | | NULL | |
| country | varchar(60) | NO | PRI | | |
| roaming_partner | varchar(60) | NO | PRI | | |
| pdp_in_total | int(8) | YES | | NULL | |
| pdp_in_ok | int(8) | YES | | NULL | |
| pdp_in_not_ok | int(8) | YES | | NULL | |
| pdp_in_ok_rate | int(8) | YES | | NULL | |
+-----------------+-------------+------+-----+---------------------+-------+
This table has new insertions hourly, that makes many different period_duration per roaming_partner:
+---------------------+----------+--------+----------+---------+-----------------------+--------------+-----------+---------------+----------------+
| period_duration | duration | sample | corner | country | roaming_partner | pdp_in_total | pdp_in_ok | pdp_in_not_ok | pdp_in_ok_rate |
+---------------------+----------+--------+----------+---------+-----------------------+--------------+-----------+---------------+----------------+
| 2014-12-16 14:00:00 | 3600 | 1 | GPRS_OUT | USA | Operator1 | 796 | 787 | 9 | 99 |
| 2014-12-16 15:00:00 | 3600 | 1 | GPRS_OUT | USA | Operator1 | 1748 | 1706 | 42 | 98 |
| 2014-12-16 16:00:00 | 3600 | 1 | GPRS_OUT | USA | Operator1 | 7 | 7 | 0 | 100 |
"ok_rate" is a percentage rate.
I need to create a SELECT that will show every single country, roaming_partner and pdp_in_ok_rate from the last 24 insertions, with the average pdp_in_ok_rate% from these insertions.
It is like i wanted that my SQL query say:
"This is the average pdp_in_ok_rate in the last 24 insertions for every operator on your table. Not in the whole table, but from these last ones."
Can someone please help me?
Does this do what you want?
select country, roaming_partner, avg(pd_in_ok_rate) as avgrate
from table t
where period_duration >= date_sub(now(), interval -1 day)
group by country, roaming_partner;
This doesn't give you the detail on the average. You can use this as a subquery, if you want the detail as well
select t.*, cr.avgrate
from table t join
(select country, roaming_partner, avg(pd_in_ok_rate) as avgrate
from table t
where period_duration >= date_sub(now(), interval -1 day)
group by country, roaming_partner
) cr
on t.country = cr.country and t.roaming_partner = cr.roaming_partner
where period_duration >= date_sub(now(), interval -1 day);

MySQL SUM ( Query works but returns unexpected results )

I am performing a MySQL Query on two tables
keyword_stats
+-------------+---------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| keywordid | int(11) | NO | MUL | NULL | |
| campaignid | int(11) | NO | | NULL | |
| clicks | int(11) | NO | MUL | NULL | |
| impressions | int(11) | NO | MUL | NULL | |
| cost | decimal(10,2) | NO | MUL | NULL | |
| conversions | int(11) | NO | MUL | NULL | |
| timestamp | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| statsdate | date | NO | MUL | NULL | |
+-------------+---------------+------+-----+-------------------+----------------+
AND
Keywords table
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| clientid | int(11) | NO | MUL | NULL | |
| campaignid | int(11) | NO | | NULL | |
| keywordid | int(11) | NO | MUL | NULL | |
| text | varchar(125) | NO | MUL | NULL | |
| status | varchar(10) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
With the following SQL Query
SELECT
k.status, statsdate,
SUM( impressions ) AS impressions, SUM( clicks ) AS clicks,
SUM( conversions ) AS conversions, SUM( cost ) AS cost
FROM keyword_stats
LEFT JOIN
(
SELECT
text,keywordid,status
FROM keywords
) AS k USING (keywordid)
WHERE
campaignid = 56486451
AND statsdate BETWEEN '2011-03-01' AND '2011-03-23'
AND k.status = "enabled"
GROUP BY keywordid
ORDER BY conversions DESC, clicks DESC, impressions DESC LIMIT 0, 10
With the results of
+---------+------------+-------------+--------+-------------+-----------+
| status | statsdate | impressions | clicks | conversions | cost |
+---------+------------+-------------+--------+-------------+-----------+
| enabled | 2011-03-01 | 71256166 | 242079 | 4247 | 891572.71 |
| enabled | 2011-03-01 | 1101 | 10 | 1 | 43.19 |
| enabled | 2011-03-01 | 210 | 6 | 0 | 23.40 |
| enabled | 2011-03-01 | 331 | 4 | 0 | 15.29 |
| enabled | 2011-03-01 | 672 | 3 | 0 | 11.41 |
| enabled | 2011-03-01 | 486 | 2 | 0 | 8.93 |
| enabled | 2011-03-01 | 254 | 2 | 0 | 9.48 |
| enabled | 2011-03-01 | 2201 | 1 | 0 | 2.96 |
| enabled | 2011-03-01 | 581 | 1 | 0 | 3.25 |
| enabled | 2011-03-01 | 483 | 1 | 0 | 4.39 |
+---------+------------+-------------+--------+-------------+-----------+
10 rows in set (12.12 sec)
The query runs and performs as expected, except as you may see the first result contains unexpected results, since it is impossible for any keywords to have that amount of clicks, conversions or cost as a sum total I'm trying to figure where MySQL is combining the totals to achieve that result
EDIT ADDED KEYWORDID
+------------+---------+------------+-------------+--------+-------------+-----------+
| keywordid | status | statsdate | impressions | clicks | conversions | cost |
+------------+---------+------------+-------------+--------+-------------+-----------+
| 2147483647 | enabled | 2011-03-01 | 71256166 | 242079 | 4247 | 891572.71 |
| 101936939 | enabled | 2011-03-01 | 1101 | 10 | 1 | 43.19 |
| 23039553 | enabled | 2011-03-01 | 210 | 6 | 0 | 23.40 |
| 117364874 | enabled | 2011-03-01 | 331 | 4 | 0 | 15.29 |
| 18862051 | enabled | 2011-03-01 | 672 | 3 | 0 | 11.41 |
| 16695651 | enabled | 2011-03-01 | 486 | 2 | 0 | 8.93 |
| 14690232 | enabled | 2011-03-01 | 254 | 2 | 0 | 9.48 |
| 18046691 | enabled | 2011-03-01 | 2201 | 1 | 0 | 2.96 |
| 22232901 | enabled | 2011-03-01 | 581 | 1 | 0 | 3.25 |
| 15072731 | enabled | 2011-03-01 | 483 | 1 | 0 | 4.39 |
+------------+---------+------------+-------------+--------+-------------+-----------+
10 rows in set (11.99 sec)
keywordid is a PRIMARY KEY in neither table.
Most probably, you have a keywordid with lots of records in both tables which results in a cross join on this keywordid.
Also note that, first, a LEFT JOIN is redundant in your query since your are filtering on k.status, and, second, MySQL is not that good in optimizing inline views.
Just use this:
SELECT k.status, statsdate,
SUM( impressions ) AS impressions, SUM( clicks ) AS clicks,
SUM( conversions ) AS conversions, SUM( cost ) AS cost
FROM keyword_stats
JOIN keywords
USING (keywordid)
WHERE campaignid = 56486451
AND statsdate BETWEEN '2011-03-01' AND '2011-03-23'
AND k.status = "enabled"
GROUP BY
keywordid
ORDER BY
conversions DESC, clicks DESC, impressions DESC
LIMIT 0, 10
Do you need the information for each day? or do you need the data sum for all days?
If you want data for each day put "statsdate" in your group by expression.
Then, I thik that you don't need make a subquery. You can put the table name right in left join.
If you want the data for each "keywordid" put "keywordid" in the result fields. Status is not mandatory because always is "enabled"
Example:
SELECT
keywordid, statsdate,
SUM( impressions ) AS impressions, SUM( clicks ) AS clicks,
SUM( conversions ) AS conversions, SUM( cost ) AS cost
FROM keyword_stats
LEFT JOIN keywords k USING (keywordid)
WHERE
campaignid = 56486451
AND statsdate BETWEEN '2011-03-01' AND '2011-03-23'
AND k.status = "enabled"
GROUP BY keywordid, statsdate
ORDER BY conversions DESC, clicks DESC, impressions DESC LIMIT 0, 10