leading 0 not displaying in mysql table result - php

just concatenating two values to one column in a mysql table. First Value from mysql table and second value from PHP constant saved as define('ACCOUNTCODESUFFIX','016');.
MySql query somewhat looks like
SELECT CONCAT_WS(\' \', mbrs.firstname, mbrs.lastname) AS fullname,
CONCAT_WS(\'-\',gl.code, '.ACCOUNTCODESUFFIX.') AS code
FROM allTbls
INNER JOIN generalledgertbl gl ON (allTbls.claim_type=gl.claimtype
AND allTbls.claim_category=gl.claimtitle
AND allTbls.claimoption=gl.claimoption)
Output:
fullname | code
name1 | 12345-16
name2 | 23456-16
How to have Output like this without using LPAD()
fullname | code
name1 | 12345-016
name2 | 23456-016

This will do it, and without all that escaping that is probably causing the confusion
define('ACCOUNTCODESUFFIX','016');
$sql = "SELECT CONCAT_WS(' ', mbrs.firstname, mbrs.lastname) AS fullname,
CONCAT_WS('-',gl.code, '" . ACCOUNTCODESUFFIX . "') AS code
FROM allTbls
INNER JOIN generalledgertbl gl ON (allTbls.claim_type=gl.claimtype
AND allTbls.claim_category=gl.claimtitle
AND allTbls.claimoption=gl.claimoption)";
echo $sql;
RESULT:
SELECT CONCAT_WS(' ', mbrs.firstname, mbrs.lastname) AS fullname,
CONCAT_WS('-',gl.code, '016') AS code
FROM allTbls
INNER JOIN generalledgertbl gl ON (allTbls.claim_type=gl.claimtype
AND allTbls.claim_category=gl.claimtitle
AND allTbls.claimoption=gl.claimoption)

Related

mysql group and order rows

I have following table 'persons' with same persons in different rows
id | firstname | surname | date_created
------------------------------------------------------
3 | Nelli | Schaller | 2017-08-22 20:57:19
------------------------------------------------------
4 | Carl | Schaller | 2019-06-21 08:29:45
------------------------------------------------------
48 | Nelli | Schaller | 2020-06-25 13:06:09
------------------------------------------------------
49 | Carl | Schaller | 2020-06-25 13:06:09
What I want to get are all unique Schallers with the biggest id / newest date_created value.
I tried this
SELECT id, CONCAT(surname, ", ", firstname) AS person, date_created
FROM persons
WHERE
surname LIKE "schall%"
GROUP by firstname, surname
ORDER BY date_createdDESC, surname ASC LIMIT 0, 10
but get only as expected the first two entries (id 3 and 4) but I need 48 and 49.
As mentioned in some comment in this case the LIKE statement isn't necessary but in real live it will be the source for an autocomplete field so I need the LIKE
Any idea how to manage that?
Use NOT EXISTS:
SELECT p.id, CONCAT(p.surname, ', ', p.firstname) AS person, p.date_created
FROM persons p
WHERE p.surname LIKE '%schall%'
AND NOT EXISTS (SELECT 1 FROM persons WHERE firstname = p.firstname AND surname = p.surname AND id > p.id)
ORDER BY p.date_created DESC, person
If the condition to pick the latest of each group is the column date_created then change:
...AND id > p.id
with
...AND date_created > p.date_created
You could use subquery with group for max id
select t.max_id, t.person, m.date_created
from (
SELECT max(id) max_id, CONCAT(surname, ", ", firstname) AS person
FROM persons
WHERE surname LIKE "schall%"
ORDER BY date_createdDESC, surname ASC
GROUP BY CONCAT(surname, ", ", firstname)
) t
inner join persons m ON CONCAT(m.surname, ", ", m.firstname) = t.person
and m-id = t.max_id
SELECT p.*
FROM persons p
LEFT JOIN persons p2 ON p2.firstname = p.firstname
AND p2.lastname = p.lastname
AND p2.date_created > p.date_created
WHERE p2.id IS NULL
This is SQL Server syntax but MySQL is probably similar.
I'm assuming your id field doesn't need to be checked as well as the date_created since it's an identity column and would be larger anyway for the latter created records, but obviously adjust to your actual data.

sql join repeating results

I need to make a list printing all the clients ordered by the gym name, but it's repeating the gym name the same number of gym's clients. If gym1 have 4 clients, the echo is printed 4 times.
The tables/columns are:
members (id, gym, name, etc...)
and
gym (gymID, gym_name, etc...).
member.gym is to know to what gym the client belongs (gym.gymID)
if ($stmt = $mysqli->prepare(" SELECT DISTINCT g.*, m.*
FROM gym g
INNER JOIN members m ON m.gym = g.gymID")) {
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array()) {
echo 'Sport center: ' . $row['gym_name'] . '<br>';
// here print the gym's clients list
}
}
DISTINCT is not working... What is the problem??
That's the normal behavior.
Example.
Consider the following tables
Table "gym"
-----------
gym_id | gym_name
-------+----------
1 | Gym A
2 | Gym B
Table "members"
---------------
member_id | gym_id | member_name
----------+--------+------------
1 | 1 | Bob
2 | 1 | Jeff
And now, execute this query:
select g.gym_id, g.gim_name, m.member_id, m.member_name
from gym as g
inner join members as m on g.gym_id = m.gym_id;
Result:
gym_id | gym_name | member_id | member_name
-------+----------+-----------+-------------
1 | Gym A | 1 | Bob
1 | Gym B | 2 | Jeff
That happens because each row in the gym table is matched with a row in the members name. Even if you use select distinct, the result would be the same, because every row is different.
I think what you want is an output like this:
Gym A
Bob
Jeff
Although that can be done directly in SQL, it's easier to handle it directly with PHP, because doing it in SQL would be a real pain in the neck would require writing quite a complex query. I'm not quite good with PHP, but it could be something like this:
/*
You don't need "DISTINCT", but you need "ORDER BY" to make this work
*/
if ($stmt = $mysqli->prepare(" SELECT g.*, m.*
FROM gym g
INNER JOIN members m ON m.gym = g.gymID
ORDER BY g.gymID")) {
$stmt->execute();
$result = $stmt->get_result();
$gym = "";
while ($row = $result->fetch_array()) {
if($row['gym_name'] != $gym)
echo 'Sport center: ' . $row['gym_name'] . '<br>';
echo ' Member: ' . $row['member_name'] . '<br>';
$gym = $row['gym_name'];
}
}
First, drop the DISTINCT and slap in an ORDER BY:
SELECT g.*, m.*
FROM gym g
INNER JOIN members m ON m.gym = g.gymID
ORDER BY g.name;
Now, adjust your PHP code to only print the gym name if it's different from the last gym you printed.
SELECT g.*, m.*
FROM gym g
INNER JOIN members m ON m.gym = g.gymID
ORDER BY g.name,gym_clients;
I dont know the name of Gym Name column & gym Client Column So, Please Change the name if they are not correctly spelled.
I hope this will work for you
This should work:
SELECT *
FROM gym g
LEFT JOIN members m
ON g.gym_ID=m.gym_id
GROUP BY g.gym_name

Count and concatenate MySQL entries

Essentially, I have a table that is like this:
FirstName, LastName, Type
Mark, Jones, A
Jim, Smith, B
Joseph, Miller, A
Jim, Smith, A
Jim, Smith, C
Mark, Jones, C
What I need to do is be able to display these out in PHP/HTML, like:
Name | Total Count Per Name | All Type(s) Per Name
which would look like...
Mark Jones | 2 | A, C
Jim Smith | 3 | B, A, C
Joseph Miller | 1 | A
Jim Smith | 3 | B, A, C
Jim Smith | 3 | B, A, C
Mark Jones | 2 | A, C
I have spent time trying to create a new table based off the initial one, adding these fields, as well as looking at group_concat, array_count_values, COUNT, and DISTINCT, along with other loop/array options, and cannot figure this out.
I've found a number of answers that count and concatenate, but the problem here is I need to display each row with the total count/concatenation on each, instead of shortening it.
How about doing it like this?
SELECT aggregated.* FROM table_name t
LEFT JOIN (
SELECT
CONCAT(FirstName, ' ', LastName) AS Name,
COUNT(Type) AS `Total Count Per Name`,
GROUP_CONCAT(Type SEPARATOR ',') AS `All Type(s) Per Name`
FROM table_name
GROUP BY Name) AS aggregated
ON CONCAT(t.FirstName, ' ', t.LastName) = aggregated.Name
Without an ORDER BY clause, the order the rows will be returned in is indeterminate. Nothing wrong with that, by my personal preference is to have the result to be repeatable.
We can use an "inline view" (MySQL calls it a derived table) to get the count and the concatenation of the Type values for (FirstName,LastName).
And then perform a join operation to match the rows from the inline view to each row in the detail table.
SELECT CONCAT(d.FirstName,' ',d.LastName) AS name
, c.total_coount_per_name
, c.all_types_per_name
FROM mytable d
JOIN ( SELECT b.FirstName
, b.LastName
, GROUP_CONCAT(DISTINCT b.Type ORDER BY b.Type) AS all_types_per_name
, COUNT(*) AS total_count_per_name
FROM mytable b
GROUP
BY b.FirstName
, b.LastName
) c
ON c.FirstName = d.FirstName
AND c.Last_name = d.LastName
ORDER BY d.FirstName, d.LastName
If you have an id column or some other "sequence" column, you can use that to specify the order the rows are to be returned; same thing in the GROUP_CONCAT function. You can omit the DISTINCT keyword from the GROUP_CONCAT if you want repeated values... 'B,A,B,B,C',

Combining several database table together?

I have two tables tour_foreign&tour_foreign_residence in database and want merger this two table together that get output from PHP code as following example:
My tables and values it:
I want get as output tour_foreign.id = tour_foreign_residence.relation :
One-week tour of Istanbul_1 | 88888 & 99999 $ 112233 $ 445566 | Three nights and two days | 15:29
One-week tour of Istanbul_2 | 55555 & 66666 $ 77777 | Three nights and two days | 12:03
One-week tour of Istanbul_3 | 11111 & 22222 $ 33333 $ 44444 | Three nights and two days | 12:03
My try is this but it don't give to me what that I want in above:
$this -> db -> query("
SELECT
#rownum := #rownum + 1 rownum,
tour_foreign.id,
tour_foreign.name,
tour_foreign_residence.name_re,
tour_foreign.term,
tour_foreign.time_go,
tour_foreign.time_back,
tour_foreign.type_of_vehicle
FROM tour_foreign
INNER JOIN tour_foreign_residence
ON ( tour_foreign.id = tour_foreign_residence.relation )
JOIN (SELECT #rownum := 0) r
WHERE tour_foreign.name LIKE "%' . $find . '%"
OR tour_foreign_residence.name_re LIKE "%' . $find . '%"
")
How can fix it?
Try using GROUP_CONCAT() to join the names from you tour_foreign_residence table
Not sure why you are joining on #rownum, it might be messing with your result set. Try taking it out and see if it works.
Your inner join looks ok, except I have never seen it with the wrapped parens, but I suspect it will work as expected. To test your query you could remove the complicated where clause and just put something like where tour_foreign.id = 1.
Something like:
SELECT
tf.*
FROM
tour_foreign AS tf
INNER JOIN
tour_foreign_residence AS tfr
ON
tfr.relation = tf.id
WHERE
tf.id = 1
I implemented aliases for your longer table names (tf, and tfr) as they are easier to work with.

Left Join duplicates

I have several tables I need to query in order to get all the rows for a certain user.
The tables basically look like this
contact
=======
id_contact PK
firstName
lastName
...
contact_phone
===============
id_contact_phone, PK
id_contact, FK
id_phone_type, FK
phone
...
phone_type
============
id_phone_type PK
phone_type
....
And there's a bunch of tables similar to those except they are for email, phone etc. I need to display all that information for a given contact, I'm using several LEFT JOIN but I'm unsure on how to output the information.
This is my query
SELECT contact.id_contact, contact.lastName, contact.firstName, contact_email.email, email_type.email_type, contact_phone.phone, phone_type.phone_type, contact_company.contact_title, company.company_name
FROM contact
LEFT JOIN contact_email
ON contact.id_contact = contact_email.id_contact
LEFT JOIN email_type
ON contact_email.id_email_type = email_type.id_email_type
LEFT JOIN contact_phone
ON contact.id_contact = contact_phone.id_contact
LEFT JOIN phone_type
ON contact_phone.id_phone_type = phone_type.id_phone_type
LEFT JOIN contact_company
ON contact.id_contact = contact_company.id_contact
LEFT JOIN company
ON contact_company.id_company = company.id_company
WHERE contact.id_contact = $cid
My problem is that if a certain contact has several phone numbers, emails etc. the query will obviously return more than 1 row so I'm not exactly sure how to display the information since most of the columns will be duplicates of each others. Here's an example of what that query might return
+===========================================================================================+
| id_contact | lastName | firstName | email | email_type | phone | phone_type |
+===========================================================================================+
| 1 | Doe | John | john.doe#123.com | Work | 555-1234 | Work |
+------------+----------+-----------+------------------+------------+----------+------------+
| 1 | Doe | John | john.doe#123.com | Work | 555-2222 | Mobile |
+-------------------------------------------------------------------+----------+------------+
| 1 | Doe | John | jdoe#email.com | Personal | 555-1234 | Work |
+------------+----------+-----------+------------------+------------+----------+------------+
| 1 | Doe | John | jdoe#email.com | Personal | 555-2222 | Mobile |
+-------------------------------------------------------------------+----------+------------+
How can I display the information in php without having redundant data and can my query be optimized?
mysql has a wonderful group_concat function. Combined with GROUP BYid_contact`, this will do what you want. For your example:
SELECT contact.id_contact, contact.lastName, contact.firstName,
GROUP_CONCAT(CONCAT(contact_email.email, ' : ', email_type.email_type) SEPARATOR ', ') AS email,
GROUP_CONCAT(CONCAT(contact_phone.phone, ' : ', phone_type.phone_type) SEPARATOR ', ') AS phone,
contact_company.contact_title, company.company_name
FROM contact
LEFT JOIN contact_email
ON contact.id_contact = contact_email.id_contact
LEFT JOIN email_type
ON contact_email.id_email_type = email_type.id_email_type
LEFT JOIN contact_phone
ON contact.id_contact = contact_phone.id_contact
LEFT JOIN phone_type
ON contact_phone.id_phone_type = phone_type.id_phone_type
LEFT JOIN contact_company
ON contact.id_contact = contact_company.id_contact
LEFT JOIN company
ON contact_company.id_company = company.id_company
WHERE contact.id_contact = $cid
Note that I've never used GROUP_CONCAT around a normal CONCAT, but I see no reason why it wouldn't work.
If your email and phone types are consistent you might could flatten it to one row by returning the different types as projected columns, for example for the email types:
SELECT contact.id_contact, contact.lastName, contact.firstName,
contact_company.contact_title, company.company_name, work_email.email AS work_email,
personal_email.email as personal_email, mobile_phone.phone as mobile_phone,
work_phone.phone as work_phone
FROM contact
LEFT JOIN contact_email AS work_email
ON (contact.id_contact = work_email.id_contact AND
work_email.id_email_type = email_type.id_email_type AND
email_type.email_type = 'Work')
LEFT JOIN contact_email AS personal_email
ON (contact.id_contact = personal_email.id_contact AND
personal_email.id_email_type = email_type.id_email_type AND
email_type.email_type = 'Personal')
LEFT JOIN contact_phone AS mobile_phone
ON (contact.id_contact = mobile_phone.id_contact AND
mobile_phone.id_phone_type = phone_type.id_phone_type AND
phone_type.phone_type = 'Mobile')
LEFT JOIN contact_phone AS work_phone
ON (contact.id_contact = work_phone.id_contact AND
work_phone.id_phone_type = phone_type.id_phone_type AND
phone_type.phone_type = 'Work')
WHERE contact.id_contact = $cid
If you have an inconsistent/unknown number of emails or phone numbers, etc, then you might be better off retrieving the data via multiple select statements. It really all depends on how you want to use the data on the web server side. Odds are that you don't actually need it in this table format though.
If you're worried about the performance of running multiple queries, remember that you can sometimes put multiple statements in a single query and have multiple result sets returned. I don't know if this is something that you can do with PHP but I would assume it is.
Since the types are unknown you can use some grouping on the PHP side by expanding on another answer in a similar question on PHP: Grouping Records from While Loop
First be sure that you're ordering on the id_contact and types in the query:
...
WHERE contact.id_contact = $cid
ORDER BY contact.id_contact, email_type.email_type, phone_type.phone_type
Then do a manual grouping on the row displays while looping through the result rows:
$contact_id = 0;
while($row = mysql_fetch_array($result))
{
if( $row['contact_id'] != $contact_id)
{
echo '<hr><br><h3>Contact: ' . $row['first_name'] . $row['last_name'] . '</h3>';
$contact_id= $row['contact_id'];
$phone_type = null;
$email_type = null;
}
if ($row['email_type] != $email_type)
{
echo $row['email_type'] . ' Email: ' . $row['email'];
$email_type = $row['email_type']
}
if ($row['phone_type] != $phone_type)
{
echo $row['phone_type'] . ' Phone: ' . $row['phone'];
$phone_type = $row['phone_type']
}
}

Categories