Selecting Individual rows using LIMIT - mysql

I'm trying to figure out if there's anyway to use GROUP_CONCAT to select rows based on these parameters.
What I'm trying to to get the lowest time for every single style/zonegroup.
AKA:
Lowest Time for Style 0 ZoneGroup 0
Lowest Time for Style 0 ZoneGroup 1
Lowest Time for Style 0 ZoneGroup 2
Lowest Time for Style 1 ZoneGroup 0
Lowest Time for Style 2 ZoneGroup 0
...
I could have multiple queries sent through my plugin, but I would like to know if this could be firstly eliminated with a GROUP_CONCAT function, and if so -how.
Here's what I could do, but I'ld like to know if this could be converted into one line.
for (int i = 0; i < MAX_STYLES; i++) {
for (int x = 0; x < MAX_ZONEGROUPS; x++) {
Transaction.AddQuery("SELECT * FROM `t_records` WHERE mapname = 'de_dust2' AND style = i AND zonegroup = x ORDER BY time ASC LIMIT 1;");
}
}
Thanks.

You don't need group_concat(). You want to filter records, so use WHERE . . . in this case with a correlated subquery:
select r.*
from t_records r
where r.mapname = 'de_dust2' and
r.timestamp = (select min(r2.timestamp)
from t_records r2
where r2.mapname = r.mapname and
r2.style = r.style and
r2.zonegroup = r.zonegroup
);

Related

MySql: Order randomly when order is 0, but use numbers before

I have this table
And I wanna retrieve all data but in a certain order. I want it to be orderd by the field order, but with 0 meaning at random and AFTER the actual numbers in that field have been ordered.
So if I did this:
var sqlString = "SELECT * \
FROM 10561_13581_tblOffers \
WHERE isVisible = 1 \
LIMIT " + start + "," + count
I want the result to be either:
"bücher oder so" - order 1
"frau mit haar" - order 3
"stein" - order 0
"ordermy" - order 0
OR the last two reversed, as they are supposed to be randomly ordered
"bücher oder so" - order 1
"frau mit haar" - order 3
"ordermy" - order 0
"stein" - order 0
But in both cases, order 1 and 3 are in order.
How would I make my query to have the desired result?
(ofc, this can be done with a lot more order numbers and a lot more rows with a 0 for order)
The boolean expression order = 0 is evaluated as 1 for true or 0 for false and can be used in the ORDER BY clause:
SELECT *
FROM 10561_13581_tblOffers
WHERE isVisible = 1
ORDER BY `order` = 0, --this will send all 0s at the end of the resultset
`order`
If you actually want all 0s to be sorted randomly you can add RAND() function:
ORDER BY `order` = 0,
`order`,
RAND()
You can use
ORDER BY CASE
WHEN order = 0 THEN 99999999
ELSE order END
like that the 0's will come at the end in no particular order.

Is there a way to make an AND operation over a column of TINYINT(1) in MYSQL?

I got the following table and I need to return 1 if all rows have disponibilidad = 1
The following QUERY works just fine, but i was looking for a more efficient way of doing it.
QUERY:
SELECT IF(AVG(disponibilidad) < 1, 0, 1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
RESULT:
As I see it, with an 'AND' it would be far more efficient, since it wouldn't have to do AVG().
MySql does not support a boolean AND aggregate function like Postgresql's bool_and.
Why not a simple MIN():
SELECT MIN(disponibilidad) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
This will return 1 only if all values of the column are 1 (provided the column is not nullable) and 0 if there is at least one row with 0.
How about something like
SELECT IF(COUNT(*)>0,0,1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1
AND disponibilidad <> 1
so that if there are any rows where disponibilidad is not 1, you output 0, otherwise if it's zero (so all disponibilidad values are 1) you output 1?

How return only value change from a mysql query without using php?

I have 2 mysql tables with 500.000 items
first with items price, items id, and ticket number
second with ticket_number, date of sales and total_price of ticket
by now i use this query
SELECT items.pri,ticket.date,items.crd,items.plu
FROM items ,ticket
WHERE
(items.crd = 25 OR items.crd = 30) AND items.SeqNbr = ticket.SeqNbr
then in php:
$val_1 = array();
$price1 = 0;
while($row = mysql_fetch_array($query))
{
if($row['crd'] == 25)
{
$prix = $row['pri'];
if($prix != $price1)
{
$val_1[] = array( (int)$row['date']*1000,(float)$row['pri']);
$price1 = $prix;
}
}
}
return:
[[1388552879000,1.519],[1389136505000,1.498],[1392420222000,1.514],[1394667334000,1.499],[1395373887000,1.478],[1395963467000,1.499],[1396649284000,1.52],[1397513210000,1.542],[1398384245000,1.556],[1399347974000,1.536],[1400910286000,1.553],[1403216692000,1.58],[1405029076000,1.563]]
goal is obtain an array with price change and date to build a charts of price fluctuation.
but with more than 500.000 records this is extremly slow (15 sec)
is there any possibilities to build mysql query that return the same array ?
Thanks
First you need to check where is the bottleneck, on the query or on the loop.
If it is on the query, check if you have the right index. If not, try adding index for the fields items.crd, items.SeqNbr and ticket.SeqNbr.

More efficient active record grouping

Im trying to check 2.5 second intervals for records and add an object to an array based on the count. This way works but its far too slow. thanks
#tweets = Tweet.last(3000)
first_time = #tweets.first.created_at
last_time = #tweets.last.created_at
while first_time < last_time
group = #tweets.where(created_at: (first_time)..(first_time + 2.5.seconds)).count
if group == 0 || nil
puts "0 or nil"
first_id + 1
array << {tweets: 0}
else
first_id += group
array << {tweets: group}
end
first_time += 2.5.seconds
end
return array.to_json
end
What you really need is the group_by method on the records you've retrieved:
grouped = #tweets.group_by do |tweet|
# Convert from timestamp to 2.5s interval number
(tweet.created_at.to_f / 2.5).to_i
end
That returns a hash with the key being the time interval, and the values being an array of tweets.
What you're doing in your example probably has the effect of making thousands of queries. Always watch log/development.log to see what's going on in the background.

How to include zero when counting with a MySQL GROUP BY expression

I'd like to count the number events that occur on each day over the last month, but also include a count of zero when no events are found. Is that possible?
Here's what I'm starting from...
SELECT COUNT(*) AS count,
DATE(usage_time_local) AS d
FROM usages
WHERE user_id=136
AND DATE(usage_time_local) >= DATE('2011-04-24')
AND DATE(usage_time_local) <= DATE('2011-05-24')
GROUP BY DATE(usage_time_local);
UPDATE: Given the answer, I implemented a code solution by initializing a loop and then filling in the details.
$dailyCount = array();
for( $i=1; $i<=30; $i++ ) {
$day = date('Y-m-d',(time()-($i*24*60*60)));
$dailyCount[$day] = 0;
}
foreach( $statement as $row ) {
$dailyCount[$row['d']] = $row['count'];
}
You can't do this with standard SQL queries - you'd be trying to group on a date(s) that doesn't exist in the table.
Standard workaround is to make a temporary table that contains the date range in sequential order with no gaps, join that against your table and do the count/aggregate as usual.