Not getting any results back from a raw query in Laravel - php

I have a raw query and when I run this query in phpMyAdmin it returns 3 results but when I try to use Laravel Query Builder I get an empty array.
My query
SELECT id, reply_text, sending_time
FROM sms_sender_inbox_replies
WHERE phone_number
IN ('+1234567819', '+19873216154', '+15984989898')
AND id IN (
SELECT MAX( id )
FROM sms_sender_inbox_replies
GROUP BY phone_number
)
Result:
+----+-----------------+---------------------+
| id | reply_text | sending_time |
+----+-----------------+---------------------+
| 87 | This is a test | 2019-07-30 08:25:26 |
| 54 | And another one | 2019-07-29 06:35:11 |
| 12 | Last test | 2019-06-16 09:44:26 |
+----+-----------------+---------------------+
But when I try to do this query with Laravel I get back an empty array []
dump($phone_numbers);
// 0 => "+1234567819"
// 1 => "+19873216154"
// 2 => "+15984989898"
$phone_numbers = implode("','", $phone_numbers);
dump($phone_numbers);
// +1234567819','+19873216154','+15984989898
dump("SELECT id, reply_text, sending_time
FROM sms_sender_inbox_replies
WHERE phone_number IN ('$phone_numbers')
AND id IN (
SELECT MAX(id)
FROM sms_sender_inbox_replies
GROUP BY phone_number
)");
// SELECT id, reply_text, sending_time
// FROM sms_sender_inbox_replies
// WHERE phone_number
// IN ('+1234567819', '+19873216154', '+15984989898')
// AND id IN (
// SELECT MAX( id )
// FROM sms_sender_inbox_replies
// GROUP BY phone_number
// )
$replies = DB::connection('second_connection')
->select("
SELECT id, reply_text, sending_time
FROM sms_sender_inbox_replies
WHERE phone_number IN (':phone_numbers')
AND id IN (
SELECT MAX(id)
FROM sms_sender_inbox_replies
GROUP BY phone_number
)
", ['phone_numbers' => $phone_numbers]);
dump($replies);
// []
P.S. Here is the output of the Query Log
I can't understand why it is returning an empty array. But when I run the raw query in phpMyAdmin it returns results so I know that the query is correct.
Array
(
[0] => Array
(
[query] =>
SELECT id, reply_text, sending_time
FROM sms_sender_inbox_replies
WHERE phone_number IN (':phone_numbers')
AND id IN (
SELECT MAX(id)
FROM sms_sender_inbox_replies
GROUP BY phone_number
)
[bindings] => Array
(
[phone_numbers] => +1234567819','+19873216154','+15984989898
)
[time] => 0.7
)
)

When you bind it like that, you try to find the phone_number IN as a single value (not as 3 values). A placeholder can only be to a single value, not to an array - but you can work around this using the QueryBuilder methods, which simplifies bindings.
$phone_numbers = ["+1234567819", "+19873216154", "+15984989898"];
$result = DB::connection('second_connection')
->table('sms_sender_inbox_replies')
->select('id', 'reply_text', 'sending_time')
->whereIn('phone_number', $phone_numbers)
->whereIn('id', DB::table('sms_sender_inbox_replies')
->selectRaw('MAX(id)')
->groupBy('phone_number')
->get())
->get();

Related

How can I echo the position number of SQL row in PHP?

Before you misread the title... I'm not asking how to echo the number of rows, I'm simply looking to find the position that the row is in.
Let's say we have five total rows:
+---------------------+
| Post ID | Author |
+---------------------+
| 463 | Me |
| 477 | Me |
| 718 | Me |
| 883 | Me |
| 276 | Me |
+---------------------+
Now I'd like to get the position of the row that contains the post ID of 718. From looking at the data, we can visually see that it is the third row in the data. How can I echo this in PHP?
when you fetch records, you may use a variable as position number.
#DB is a class connect to mysql database.
DB::init();
$sql = "SELECT * FROM RowNo ";
$stmt = DB::query( $sql );
$i = 1;
while( $rec1 = $stmt->fetch() ) {
echo "row $i : ";
print_r( $rec1 );
echo '<BR>'.PHP_EOL;
$i++;
};
result :
row 1 : Array ( [Post ID] => 8788277463 [Author] => Me )
row 2 : Array ( [Post ID] => 2894728477 [Author] => Me )
row 3 : Array ( [Post ID] => 3898994718 [Author] => Me )
row 4 : Array ( [Post ID] => 4891784883 [Author] => Me )
row 5 : Array ( [Post ID] => 1185819276 [Author] => Me )
You may use row_number :
#1. ORDER BY Post ID
SELECT * , row_number() over ( order by Post ID ) FROM RowNo order by Post ID asc
Post ID Author row_number() over ( order by `Post ID` )
1185819276 Me 1
2894728477 Me 2
3898994718 Me 3
4891784883 Me 4
8788277463 Me 5
#2. ORDER BY Post ID DESC
SELECT * , row_number() over ( order by Post ID desc ) FROM RowNo order by Post ID desc
Post ID Ascending 1 Author row_number() over ( order by `Post ID` desc )
8788277463 Me 1
4891784883 Me 2
3898994718 Me 3
2894728477 Me 4
1185819276 Me 5
#3. ORDER BY part of Post ID
SELECT * , substr(Post ID, 4, 2), row_number() over ( order by substr(Post ID, 4, 2) ) FROM RowNo order by substr(Post ID, 4, 2) asc
Post ID Author substr(`Post ID`, 4, 2) Ascending 1 row_number() over ( order by substr(`Post ID`, 4, 2) )
4891784883 Me 17 1
2894728477 Me 47 2
1185819276 Me 58 3
8788277463 Me 82 4
3898994718 Me 89 5

Merge result after query with JOIN clause in Mysql

I have two table like this:
Product
id | title
-------------------------------
1 | Skirt
2 | Pants
Product_thumbnail
id | product_id | image
-------------------------------
1 | 1 | pant.jpg
2 | 1 | shoes.png
When I want to get product with the thumbnail, I query like this:
SELECT p.*, pt.image FROM product p
LEFT JOIN product_thumbnail pt ON pt.product_id = p.id;
The output I expected
[0]=> [
[id] => 1
[image] =>
[
[0] => pant.jpg
[1] => shoes.jpg
]
]
[1]=> [
[id] => 2
[image] => null
]
But the real output
[0]=> [
id => 1
image => pant.jpg
]
[1]=> [
id => 1
image => shoes.jpg
]
[2]=> [
id => 2
image => shoes.jpg
]
As you see, there is 2 element duplicate, so I need to merge it by hand, is there any way to achieve this more easy? Because my table have many tables relate together more than this, I'm using PHP, I use array_merge_recursive() to merge them but if do like that I get duplicate value in each field, like this:
[0]=> [
[id] =>
[
[0] => 1
[1] => 1
]
[image] =>
[
[0] => pant.jpg
[1] => shoes.jpg
]
]
It's not what I want, can anyone give me an idea?
Consider the following. The code could I'm sure be written more economically, but hopefully you get the idea...
<?php
/*
DROP TABLE IF EXISTS product;
CREATE TABLE product
(id SERIAL PRIMARY KEY
,title VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO product VALUES
(1,'Hat'),
(2,'Shoe');
DROP TABLE IF EXISTS product_thumbnail;
CREATE TABLE product_thumbnail
(id SERIAL PRIMARY KEY
,product_id INT NOT NULL
,image VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO product_thumbnail VALUES
(1,1,'sombrero.jpg'),
(2,1,'stetson.png');
SELECT p.id
, p.title
, t.image
FROM product p
LEFT
JOIN product_thumbnail t
ON t.product_id = p.id;
+----+-------+--------------+
| id | title | image |
+----+-------+--------------+
| 1 | Hat | sombrero.jpg |
| 1 | Hat | stetson.png |
| 2 | Shoe | NULL |
+----+-------+--------------+
*/
require('path/to/connection/stateme.nts');
$query = "
SELECT p.id
, p.title
, t.image
FROM product p
LEFT
JOIN product_thumbnail t
ON t.product_id = p.id;
";
$result = mysqli_query($db,$query);
$old_array = array();
while($row = mysqli_fetch_assoc($result)){
$old_array[] = $row;
}
$new_array = array();
foreach ($old_array as $row) {
$new_array[$row['id']]['title'] = $row['title'];
$new_array[$row['id']]['image'][] = $row['image'];
}
$new_array = array_values($new_array); // reindex
print_r($new_array);
?>
Outputs
Array
(
[0] => Array
(
[title] => Hat
[image] => Array
(
[0] => sombrero.jpg
[1] => stetson.png
)
)
[1] => Array
(
[title] => Shoe
[image] => Array
(
[0] =>
)
)
)
MySQL doesn't support arrays, but you can aggregate the data into a string:
SELECT p.*, GROUP_CONCAT(pt.image) as images
FROM product p LEFT JOIN
product_thumbnail pt
ON pt.product_id = p.id
GROUP BY p.id;
Note that aggregating only by the id and selecting p.* is allowed and even standard SQL -- assuming that id is a primary key or declared to be unique. This is the one situation when this syntax is permitted.

Pagination from two SQL Tables with one query. Fastest Way

I have a simple Database:
Table 1: Object Table 2: Data
id | type | added object_id | key | value
------------------------ -----------------------------
1 | app | 2017 1 | name | ...
2 | app | 2017 2 | name | ...
3 | win | 2017 2 | version | ...
2 | dev_name | ...
2 | lang | ...
i created a simple pagination to show only 5 object from type apps with their infomation from the data table:
example code:
$sth = $dbh->prepare("SELECT * FROM object WHERE type = 'app' LIMIT 5");
$sth->execute;
$object = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach($object as $rows) {
$sth = $dbh->prepare("SELECT * FROM data WHERE id = $rows['id']");
$sth->execute;
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
echo $data['name'];
echo $data['version'];
echo $object['added'];
...
Is there a better way? because this is a very bad solution, i want to query only one time where i get an fetch array like this:
array(
// app with id = 1 in object table
[1] => array(
// data from the app with id = 1 in data table
[name] => ...
[version] => ...
[dev_name] => ...
[lang] => ...
// app with id = 2 in object table
[2] => array(
// data from the app with id = 2 in data table
[name] => ...
[version] => ...
[dev_name] => ...
[lang] => ...
...
one query:
SELECT * FROM object inner join data on data.id_object=object.id WHERE object.type = 'app' LIMIT 5
This query return information from two table with associate data.
I think that's what you want
If you want to group by id of the first table you can also execute this query
SELECT * FROM object inner join data on data.id_object=object.id WHERE object.type = 'app' group by object.id LIMIT 5
or
SELECT Distinct(object.id), object.type, .... FROM object inner join data on data.id_object=object.id WHERE object.type = 'app' LIMIT 5
Consider for string comparison use LIKE instead of =

how to get two rows from a table using join

this is my code
$query = $this->db
->select('*')
->join('users as receiver', 'receiver.user_id = messages.user1')
->join('users as sender', 'sender.user_id = messages.user2')
->get('messages')->result_array();
this is database
users table
user_id |username | datetime
1 | abc1 | 000000000
2 | abc2 | 000000000
messages table
msg_id | user1 | user2 | msg | timestamp
1 | 1 | 2 | hello | 000000000
i want to get records of two users as sender and receiver. but this join give me record of last join. in this case i m getting record of sender.
i want output like this
[0] => Array
(
[user1] => stdClass Object
(
[id] => 1
[username] => abc1
[datetime] => 2016-11-07 03:00:00
)
[user2] => stdClass Object
(
[id] => 2
[username] => abc2
[datetime] => 2016-11-07 00:00:00
)
[message] => stdClass Object
(
[id] => 1
[message] => hdf
[timestamp] => 2016-11-06 08:43:26
)
)
thanks in advance
Here is the SQL to create a union query that will give you two rows
select * from messages m join users u on u.user_id = m.user1 union all select * from messages m join users u on u.user_id = m.user2;
or with a join statement for two users in one row
select * from messages m join users u1 on u1.user_id = m.user1 join users u2 on u2.user_id = m.user2;

Sum php array (created from mysql results) depending on mysql values in another mysql column

One table called 18_7_ChartOfAccounts looks like this:
ID | AccountNumber
-------------
1 | 2310
2 | 2380
3 | 2610
Another table called 2_1_journal looks like this:
ID | Amount | DebitAccount
--------------------------
1 | 26.03 | 2310
2 | 200.00 | 2310
3 | 3.63 | 2380
4 | 119.83 | 2380
5 | 33.86 | 2610
6 | 428.25 | 2610
Aim is to get results that looks like this:
DebitAccount 2310 total is: 226.03
DebitAccount 2380 total is: 123.46
DebitAccount 2310 total is: 462.11
226.03 in this example is total of 26.03 + 200.00
At first mysql code
$query = "SELECT j.Amount, j.DebitAccount FROM 18_7_ChartOfAccounts AS c LEFT JOIN 2_1_journal AS j ON (c.AccountNumber = j.DebitAccount)";
$sql = $db->prepare($query);
$sql->execute();
$data = $sql->fetchAll(PDO::FETCH_ASSOC);
With print_r($data); get long list of arrays like
[31] => Array
(
[Amount] => 26.03
[DebitAccount] => 2310
[32] => Array
(
[Amount] => 200.00
[DebitAccount] => 2310
If in mysql query use SUM(j.Amount) then get only one total amount (suppose total amount of Column Amount).
With
foreach($data as $result){
if(strlen($result['Amount']) > 0 ) {
echo "Amount ". $result['Amount']. "Account name ". $result['DebitAccount']. "<br>";
print_r (array_sum($result));
}
}
Get something like this
Amount 123.97Account name 2310
2433.97Amount 26.03Account name 2310
2336.03Amount 200.00Account name 2310
Any ideas how to get necessary results (marked bold)?
Update
Changed $query to
$query = "SELECT SUM(j.Amount), j.DebitAccount FROM 18_7_ChartOfAccounts AS c LEFT JOIN 2_1_journal AS j ON (c.AccountNumber = j.DebitAccount) group by j.DebitAccount";
with print_r($data); get array like this
Array
(
[0] => Array
(
[SUM(j.Amount)] =>
[DebitAccount] =>
)
[1] => Array
(
[SUM(j.Amount)] => 110900.16
[DebitAccount] => 2310
)
[2] => Array
(
[SUM(j.Amount)] => 3660.86
[DebitAccount] => 2380
)
With array seems all works. Now with foreach changed to
echo "Amount ". $result['SUM(j.Amount)']. " Account name ". $result['DebitAccount']. "<br>";
Get
Amount 110900.16 Account name 2310
Amount 3660.86 Account name 2380
Amount 85247.40 Account name 2610
Seems also ok. Thanks
You are going about it wrong. You can get the sum through MySql statement itself.
Use the aggrgate function sum along with group by clause.
Like this,
SELECT DebitAccount,sum(Account) from 2_1_journal group by DebitAccount
Your full code:
$query = " SELECT DebitAccount,sum(Account) as Total from 2_1_journal group by DebitAccount";
$sql = $db->prepare($query);
$sql->execute();
$data = $sql->fetchAll(PDO::FETCH_ASSOC);
foreach($data as $result){
if(strlen($result['Total']) > 0 ) {
echo "DebitAccount ". $result['DebitAccount']. "Total is: ". $result['Total']. "<br>";
print_r (array_sum($result));
}
}
SELECT DebitAccount, SUM(Amount)
FROM 2_1_journal
GROUP BY DebitAccount
You have to use the GROUP BY in the query
SELECT DebitAccount, SUM(Amount) AS Amount FROM 2_1_journal GROUP BY DebitAccount

Categories