PHP: Fetching data from *strange* MySQL database - php

I have a closed-source software written in C#/.NET from a VoIP company which is impossible to customize and wanted to create custom front-end using PHP. I gained access to the database and now see how it functions. I wanted to output the user his 'speed dial' numbers, but having issue solving it. Here are the tables structures:
'customer' table
+-------------------------------------------------------------------------+
| CustomerID | FirstName | LastName | Balance | Email | Password | Status |
|-------------------------------------------------------------------------|
| 1 | Homer | Simpson | 5.00 | h#s.s | iheartm | 1 |
| 2 | Marge | Simpson | 3.00 | m#s.s | ihearth | 1 |
+-------------------------------------------------------------------------+
'calls' table
+------------------------------------------------------------------------+
| CallID | Caller | Callee | ServiceID | Duration | Cost | CustomerID |
|------------------------------------------------------------------------|
| 1 | 1234567 | 7654321 | 30 | 60 | 1.00 | 1 |
| 2 | 7654321 | 1234567 | 45 | 120 | 2.00 | 2 |
+------------------------------------------------------------------------+
'ani' (speed-dial) table
+---------------------------------------+
| PhoneNumber | ServiceID | ContactName |
|---------------------------------------|
| 1234567 | 45 | Homer |
| 7654321 | 30 | Marge |
+---------------------------------------+
As you can see, 1234567 is Homer's phone number and in Marge's speed dial list and 7654321 is Marge's number in Homer's list. Just like I can pull up customer's balance when logged in using: $current_user['Balance'];, is there way to show user his 'speed dial' numbers in PHP?

This request doesn't achieve what you want ?
SELECT
a.CustomerID, a.FirstName, a.LastName, a.Balance, a.Email, a.Status,
b.ServiceID,
(SELECT GROUP_CONCAT(CONCAT(ContactName,':',PhoneNumber)) FROM ani GROUP BY PhoneNumber WHERE ServiceID = b.ServiceID)
FROM customer a
LEFT JOIN calls b ON a.CustomerID = b.CustomerID
WHERE a.CustomerID = 'replace_by_customer_id'
This should fetch the data of the customer table, plus a string that results from concatenating the speed-dial numbers of the customer connected.
I assume that a customerid corresponds to one unique serviceid found in calls, and the serviceid in the table ani indicates the owner of the speed-dial number. But it seems a weird architecture, so you should give us more data or informations about the tables...

There seems to be a missing relation from ServiceID to a specific entry in customer. It would seem strange that the calls table would provide that relation, it should merely use it.
With only the information you supplied you can only join calls to link the CustomerID with the ServiceID which I suppose you have. The query would look like this:
SELECT ContactName, PhoneNumber FROM ani
LEFT JOIN calls ON ani.ServiceID=calls.ServiceID
WHERE calls.CustomerID=xxx

Related

Summation Query with join codeigniter

I have 2 tables. One with a list of clients and another with a list of data. I am trying to create a table in my view that lists the client name along with the sum of a column(job_total) in the data table. I am able to write a query that works fine in most situations. The problem is, if I have not yet created a record in the data table I need to still display the client name with a balance of zero on my table in my view. Need some direction on how to handle this. I was thinking I need to query my list of clients and loop through that query just not sure how to do it.
I want my view to look like below:
+-------------+---------+
| Client Name | Balance |
+-------------+---------+
| xxx | $75.00 |
| xxx | $100.00 |
| xxx | $0.00 |
+-------------+---------+
Here is a rough layout of the two tables in my database:
cj_clients
+----+-------------+
| id | client name |
+----+-------------+
| 1 | client1 |
| 2 | client2 |
| x | xxx |
+----+-------------+
cj_data
+----+-----------+-----------+
| id | client_id | job_total |
+----+-----------+-----------+
| 1 | 1 | 5.00 |
| 2 | 1 | 10.00 |
| 3 | 1 | 15.00 |
+----+-----------+-----------+
The below code returns the desired results except when no entries have yet been made to the cj_data table. Not sure how to still get the client in the table view with a balance of $0.
$this->db->select('client_name,client_id, sum(job_total) AS balance')
->from('cj_data')
->join('cj_clients','cj_data.client_id = cj_clients.id')
->group_by('client_name');
return $this->db->get()->result();
You need to give left join
$this->db->select('client_name,client_id, IFNULL(sum(job_total),0) AS balance')
->from('cj_data')
->join('cj_clients','cj_data.client_id = cj_clients.id',"left") // here
->group_by('client_name');
return $this->db->get()->result();
I wrote IFNULL condition if record not found or it will show all data for all clients in cj_clients
Note: the Default behaviour of CodeIgniter is it will add inner join
if join not specified

MySQL select row from one table with multiple rows in a second table

I have one table containing "Client" information, and another including "Payment" information for each client.
Simplified client table
client_id | client_name | client_status
----------+----------------+--------------
1 | John St. Peter | In Arrears
2 | Peter St. John | Up-to-date
Simplified payments table
payment_id | client_id | payment_date | payment_amount
-----------+-----------+--------------+---------------
1 | 1 | 2017-12-12 | 123.45
2 | 2 | 2017-12-15 | 234.56
3 | 1 | 2017-12-17 | 23.45
4 | 1 | 2017-12-21 | 54.32
5 | 2 | 2017-12-23 | 34.56
With the above two tables, I want to produce a single table with a single query with all the pertinent information to generate a search grid where I can filter by any column in either of the two tables, namely, filter by "client_status" from "client" table, or "client_id" from "payments" table.
payment_id | client_id | client_name | client_status | payment_date | payment_amount
-----------+-----------+----------------+---------------+--------------+---------------
1 | 1 | John St. Peter | In Arrears | 2017-12-12 | 123.45
2 | 2 | Peter St. John | Up-to-date | 2017-12-15 | 234.56
3 | 1 | John St. Peter | In Arrears | 2017-12-17 | 23.45
4 | 1 | John St. Peter | In Arrears | 2017-12-21 | 54.32
5 | 2 | Peter St. John | Up-to-date | 2017-12-23 | 34.56
So - in essence, I want to "duplicate records" in the clients table for as many times as necessary for corresponding records in the payments table to facilitate the search. I am using a premade grid tool (DataTables) which is used all over the system with a custom function made by the developer to generate the grid (so I don't want to mess with that function in fear of breaking the rest of the system), so a single query to get that data sounds like the more pragmatic approach. I also have an "Edit" feature for each row, which will edit the "client" table, and put a tabbed structure in the edit screen for the "payments" table, which currently works fine with two queries (one for the client, one getting all the payments for that client).
I have tried UNION as well as various JOIN statements (probably incorrect...), but either get syntax errors or a single result per "client" row, meaning it does not pick up in the filters.
Apologies if this is a duplicate question - I have searched, but could not find an answer that answers this scenario for me.
here is a join...
select *
from clientsTable c,
paymentsTable p
where c.client_id = p.client_id
order by p.payment_id;
that should give you everything.
edit: for empties... payments with no clients...
select *
from clientsTable c,
paymentsTable p
where c.client_id = p.client_id
or p.client_id = null
order by p.payment_id;

Retrieve data from second table when there is no column relations

I need a query to retrieve all shops that are related to specifif "industry"
My mate designed table without foreign key and as many to many relation, he used Regex when separating with ","
TABLE shops
id | phone | address | type
1 | 11111 | XXXXX | ,10,12,13
3 | 22121 | XXXXX | ,33,37,38
5 | 11111 | XXXXX | ,51,52,55
TABLE types
ID | industry | type
10 | service | taxi
12 | service | delivery
13 | service | mail
33 | primary | electriticy
37 | primary | water
38 | primary | gas
51 | edu | primary school
52 | edu | high school
55 | edu | university
60...
70...
Is there any possibility to retrieve like ex: with WHERE types.industry = 'service' in a single query?
I'm having trouble to do it, though all about Joins or Subqueries etc, but i came up with no solution.
Looking for help.
Thanks in advance
Assuming I'm understanding correctly, one option is to join using find_in_set():
select *
from shops s
join types t on find_in_set(t.id, s.type)
where t.industry = 'service'
SQL Fiddle Demo

How to handle LEFT OUTER JOIN results efficiently with PHP / PDO

Long time answer finder, first time asker here. I tried looking for an answer to this, but either it doesn't exists (doubtful) or I just can't seem to come up with the proper terminology to search with (most likely).
I'm using PHP / PDO to get data from a MariaDB database. The database has tables with a many-to-many relationship and a junction table between them like this:
people attendees events
+----+------+ +------+------+ +----+-------------------------+
| id | name | | p_id | e_id | | id | name |
+----+------+ +------+------+ +----+-------------------------+
| 1 | Bob | | 1 | 1 | | 1 | Company Christmas party |
| 2 | Anne | | 2 | 1 | | 2 | Christmas party cleanup |
| 3 | John | | 3 | 1 | | 3 | John's birthday party |
+----+------+ | 3 | 3 | +----+-------------------------+
+------+------+
I'm using a LEFT OUTER JOIN to select the events and their attendees:
SELECT events.id, events.name, people.id, people.name
FROM events
LEFT OUTER JOIN attendees
ON events.id = attendees.e_id
LEFT OUTER JOIN people
ON attendees.p_id = people.id
Now the "problem" is that the query returns multiples of the same event for each attendee as follows:
+----+-------------------------+------+------+
| id | name | id | name |
+----+-------------------------+------+------+
| 1 | Company Christmas party | 1 | Bob |
| 1 | Company Christmas party | 2 | Anne |
| 1 | Company Christmas party | 3 | John |
| 2 | Christmas party cleanup | NULL | NULL |
| 3 | John's birthday party | 3 | John |
+----+-------------------------+------+------+
Now I'm somewhat stuck with looping though the results. I want to create event objects from the results, but I want one event only as one object, adding attendees to it.
I could loop through my array of existing event objects and check if the id already exists when going through the resultset, but this seems a little inefficient. Is there a more elegant solution, possibly built into PDO?
I would do something like this:
Slightly modify your query (now we have different names for event name and person name):
SELECT events.id, events.name as event, people.id, people.name as person
FROM events
LEFT OUTER JOIN attendees
ON events.id = attendees.e_id
LEFT OUTER JOIN people
ON attendees.p_id = people.id
And parse results into array:
//$queryResult is the result returned by your query
while($row = $queryResult->fetch(PDO::FETCH_ASSOC)) {
$results[$row['event']][] = $row['person'];
}
In the end, you have an associative array that stores events and people.
print_r($results['Company Christmas party']) will return you
Array
(
[0] => Array
(
[0] => Bob
[1] => Anne
[2] => John
)
)
Regarding efficiency, I don't see anything inefficient here, linear complexity.

MySQL Count to rows as one

I have a database as laid out below.
mysql> select * from wants where itemname='lamp' order by location;
+------+--------------------+-------------+----------+----------+----------+
| sess | username | room | image | item | priority |
+------+--------------------+-------------+----------+----------+----------+
| 33 | user1#aol.com | Family Room | DSC00649 | Lamp | 1 |
| 235 | user2#yahoo.com | Family Room | DSC00649 | Lamp | 2 |
| 60 | user3#homtmail.com | Foyer | DSC00527 | Lamp | 1 |
| 197 | user4#gmail.com | Foyer | DSC00527 | Lamp | 2 |
| 189 | user4#gmail.com | Living Room | DSC00827 | Lamp | 1 |
| 273 | user5#live.com | Living Room | DSC00827 | Lamp | 2 |
+------+--------------------+-------------+----------+----------+----------+
6 rows in set (0.00 sec)
What I am trying to do is get a count of each item per room.
When I run the query it should look like:
2 Family Room Lamp user1#aol.com user2#yahoo.com
2 Foyer Lamp user3#homtmail.com user4#gmail.com
2 Living Room Lamp user4#gmail.com user5#live.com
Current Query:
$result1 = mysql_query("SELECT username, location, image, itemname, COUNT( itemname ) x FROM wants GROUP BY itemname HAVING x >1 order by location ASC")
This will give the following output:
6 Family Room Lamp luser1#aol.com user2#yahoo.com user3#homtmail.com user4#gmail.com user4#gmail.com user5#live.com
I tried to use Concat to get the count of the first two rows but that did not help,
How can i break these out to get the rooms to read separately, when the Item name is the same?
You need to group by the room instead of the item. Also sounds like you're looking for group_concat to list the users:
select count(*),
room,
group_concat(username)
from wants
where item ='lamp'
group by room
SQL Fiddle Demo

Categories