I have MySQL table as bellow
id, name, postcode, address
in my, table postcode will be like this
AX12 3NB
NB76 5BQ
AX23 6NB
AX87 6CZ
I want to get top 10 Postcode in total like postcode start with AX appear 3 times
I have Laravel project and want to do in this syntax
DB::table('users')
I want to get the total number of any postcode first 2 letters and only the top 10 records.
Thanks
First, get all the records, then use PHP to sort and reduce the size of the array. The best way to do this is with a raw query, but since you stated above that you don't want to use a raw query, this is a quick way to handle it.
$users = DB::table('users')->get();
$postcodes_array = [];
foreach ($users as $user) {
$first_two = substr($user->postcode, 0, 2);
if (isset($postcodes_array[$first_two])) {
$postcodes_array[$first_two] += 1;
} else {
$postcodes_array[$first_two] = 1;
}
}
arsort($postcodes_array);
$postcodes_array = array_slice($postcodes_array, 0, 10);
Related
I am working on a card game to use on Discord that allows up to 3 copies of any one card to be used. I can add the first copy of a card to my mysql database and get the result without a problem, but as soon as I add another copy of a card that already exists in the deck, those copies do not appear in row results when the results from the first query are queried in a second query.
var sql1 = `SELECT * FROM deck_cards WHERE deckid = '${deckid}'`;
con.query(sql1, function (err, rows, fields) {
console.log(rows)
if (!err) {
var count = rows.length;
if (count) {
var arr_cardid = rows.map(i => i.cardid);
var sql2 = `SELECT cardname FROM card_info WHERE cardid in ('${arr_cardid.join("','")}') `;
console.log(sql2)
con.query(sql2, function (err, rows, fields) {
if (!err) {
var count = rows.length;
for (i = 0; i < count; i++) {
arr_cardname = []
arr_cardname.push(rows[i].cardname)
// list = arr_cardname.join(", ")
console.log(arr_cardname)
}
}
})
}
}
})
Table in mysql: https://i.gyazo.com/fb165c1f402f5234a3501e09d715b965.png
Deckid 1 is the deck I query for in the first query. Notice cardid 2 should have 3 total copies of it in the deck. So, I should see 3 copies of cardid 2 when I display the list of cards in that deck. The copies are put into the second query (https://i.gyazo.com/8b6c8426daee2611766242961883ec37.png) However, I only see 1 result for those copies in the output (list), the first one found in row 3 (index 2) of the table. The other 2 copies added at the very end of the table do not appear from the second query results. Is there a way to make the duplicate rows appear in the results of the second query? I have seen union, inner joins, count and such that would be used for a workaround, but I figured I'd ask if there is a simpler and more efficient way to make this work.
Is this an issue with the for loop or the second .join(", ") maybe?
I want select X records from database (in PHP script), then sleep 60 seconds after continue the next 60 results...
SO:
SELECT * FROM TABLE WHERE A = 'B' LIMIT 60
SELECT SLEEP(60);
....
SELECT * FROM TABLE WHERE A = 'B' LIMIT X **where X is the next 60 results, then**
SELECT SLEEP(60);
AND etc...
How can I achievement this?
There is no such thing as "the next 60 records". SQL tables represent unordered sets. Without an order by, a SQL statement can return a result set in any order -- and even in different orders on different executions.
Hence, you first need something to guarantee the ordering . . . that is, an order by with keys that uniquely identify each row.
You can then use offset/limit to accomplish what you want. Or, you could put the code into a stored procedure and use a while loop. Or, you could do this on the application side.
In PHP:
<?php
// obtain the database connection, there's a heap of examples on the net, assuming you're using a library like mysqlite
$offset = 0;
while (true) {
if ($offset == 0) {
$res = $db->query('SELECT * FROM TABLE WHERE A = 'B' LIMIT 60');
} else {
$res = $db->query('SELECT * FROM TABLE WHERE A = 'B' LIMIT ' . $offset . ',60');
}
$rows = $db->fetch_assoc($res);
sleep(60);
if ($offset >= $some_arbitrary_number) {
break;
}
$offset += 60;
}
What you're doing is gradually incrementing the limit field by 60 until you reach a limit. The easiest way to do it is in a control while loop using true for the condition and break when you reach your invalid condition.
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.
I'm just a beginner at mysql so in school we got task to do. It goes like this. Display / print 10% of all books from books in falling order. So i tried to use limit, but it doesn't work. What can i do? My code i've tried to use:
select title, price from book
order by price desc
limit (select count(*)*0.1 from book);
thank you for your answers!
limit values have to be hard-coded constants. You can't use variables on them, e.g. select ... limit #somevar is a syntax error. You also can't use sub-queries or other dynamic values either. So you're stuck with either fetching the row count ahead of time and stuff it into the query string as a "hard-coded" value:
$ten_percent = get_from_database('select count(*) / 10 from book');
$sql = "SELECT .... LIMIT $ten_percent";
Or you simply fetch everything and then abort your loop once you've reached 10%:
$sql = "SELECT ....";
$result = mysql_query($sql) or die(mysql_error());
$total_rows = mysql_num_rows($result);
$fetched = 0;
while($row = mysql_fetch_assoc()) {
$fetched++;
if ($fetched >= ($total_rows / 10)) {
break; // abort the loop at 10%
}
... do stuff with $row
}
My Current query is:
SELECT DISTINCT DATE(vote_timestamp) AS Date, COUNT(*) AS TotalVotes FROM `votes`
WHERE vote_target_id='83031'
GROUP BY DATE(vote_timestamp) ORDER BY DATE(vote_timestamp) DESC LIMIT 30
(line breaks separated for readability)
Where vote_timestamp is a time for each "vote", Count(*) is the count for that day, and vote_target_id is the specific target of the vote.
Currently, this works for all days in which the target has at least one "vote", but I would like it to also return TotalVotes as 0 for days where there are no votes, rather than having no row at all.
Can this (and how?) be done in MySQL or PHP? (either is fine, as it is futher processed by PHP so either code can be used).
Thank you
The problem is how to generate records for days that have no rows. This SO question has some approaches.
Looking at that solution, it looks like for me it's much simpler to do this quick fix that sorta works.
$result = mysql_query($sql) or die('Internal Database Error');
if (mysql_num_rows($result) == 0) { return false; }
while($row = mysql_fetch_assoc( $result )) {
$votes[$row['Date']] = $row['TotalVotes'];
}
// fill 0s with php rather than using mysql
$dates = array_keys($votes);
for ($t = strtotime($dates[count($dates)-1]); $t <= time(); $t +=86400) {
$date = date('Y',$t).'-'.date('m',$t).'-'.date('d',$t);
if (!array_key_exists($date,$votes)) {
$votes[$date] = 0;
}
}
thanks though,