Show all columns in MySQL tables without null values in PHP - php

I have a database of historical personas with the following three tables:
t_name
t_occupation
t_location
t_name includes all the bio-infos, e.g. name, surname, dateofbirth, etc.
t_occupation lists possible occupations (writer, singer, etc.) and is the foreign key to the t_name column "id_occupation"
t_location lists all the locations with plz and links as foreign key to a couple of columns in t_name table, e.g. id_birthplace, id_placeofdeath, id_placeofliving, etc.
I'd like to generate an output of the whole database which lists all historical personas with all the columns that are not null (so for example, Persona 1 may have an id_birthplace but id_placeofdeath is unknown, so id_placeofdeath should not be listed, but the rest should).
In PHP 4.0, I used variables to store the info and worked with if-statements to generate the list (mysql_result), but this is no longer possible with PHP 7.0.
How do I do this in the latest version?
I tried the following code:
$res = mysqli_query($con,"SELECT * FROM ( SELECT t_name AS table, IF(COUNT(name), NOT NULL, name) AS column
FROM t_name
UNION ALL
SELECT t_location AS table, IF(COUNT(location), NOT NULL, location) AS column FROM t_ort
UNION ALL)
WHERE column IS NULL");
while ($dsatz = mysqli_fetch_assoc($res))
{
echo $dsatz["name"] . ", "
.$satz["location"] . "<br /> <br />";
}
The only result I get is: records found but no listing. What did I get wrong?

SELECT * FROM ( SELECT tableA AS table, IF(COUNT(column_a), NOT NULL, column_a) AS column
FROM tableA
UNION ALL
SELECT tableB AS table, IF(COUNT(column_b), NOT NULL, column_b) AS column FROM tableB
UNION ALL -- etc. ) t
WHERE column IS NULL

Related

Sql select query dealing with multiple tables

I have table employees with columns: id, employee_id with values say ABC1234 and 4 respectively.
Another table cashadvance with columns :id, date_advance, employee_id, amount with values say 3, 2018-06-20, 5, 1500.
Now i want do sql select query in PHP to show date_advance and amount for the specific user/logged in employee(username is employee_id e.g, ABC1234 plus pswd) .
I have trouble cause employee_id in cashadvance is the primary key for employee in table employees. Please help
Below is the query written for your purpose to get those data for employees in employees table and related data in cashadvance . Here an inner join is used , please run the query and let me know if you face any error .
$sql = "select *
from employees as 'emp'
inner join cashadvance as 'cad'
on cad.employee_id = emp.employee_id
where 1" ;

MySQL “NOT IN” query 3 tables

I have 3 tables course, grade and evaluation. I want comparing two tables grade and evaluation . if the data in the table grade does not exist in the table evaluation , then the data will appear (output)
" select Grade.ID_Courses,Course.ID_Courses,Grade.NAME,
Course.NAME, Grade.ID_Courses,
Evaluation.NAME,
Evaluation.Year,
Grade.Year
from Grade, Course, Evaluation
WHERE
Grade.ID_Courses=Course.ID_Courses AND
Grade.NAME=JOHN and
Grade.Year=1 and
Evaluation.NAME=GRADE.NAME and
Grade.ID_Courses NOT IN (SELECT ID_Courses FROM Evaluation where NAME=JOHN and Year=1 )
GROUP BY Grade.ID_Courses"
the problem is when the name john is not in the table evaluation then there is no output comes out .
Avoid NOT IN like the plague if
SELECT ID_Courses FROM Evaluation where `NAME`='JOHN' and Year=1
could ever contain NULL. Instead, use NOT EXISTS or Left Joins
use explicit joins, not 1980's style joins using the WHERE clause
To illustrate the misery of NOT IN:
SQL NOT IN () danger
create table mStatus
( id int auto_increment primary key,
status varchar(10) not null
);
insert mStatus (status) values ('single'),('married'),('divorced'),('widow');
create table people
( id int auto_increment primary key,
fullName varchar(100) not null,
status varchar(10) null
);
Chunk1:
truncate table people;
insert people (fullName,`status`) values ('John Henry','single');
select * from mstatus where `status` not in (select status from people);
** 3 rows, as expected **
Chunk2:
truncate table people;
insert people (fullName,`status`) values ('John Henry','single'),('Kim Billings',null);
select * from mstatus where status not in (select status from people);
no rows, huh?
Obviously this is 'incorrect'. It arises from SQL's use of three-valued logic,
driven by the existence of NULL, a non-value indicating missing (or UNKNOWN) information.
With NOT IN, Chunk2 it is translated like this:
status NOT IN ('married', 'divorced', 'widowed', NULL)
This is equivalent to:
NOT(status='single' OR status='married' OR status='widowed' OR status=NULL)
The expression "status=NULL" evaluates to UNKNOWN and, according to the rules of three-valued logic,
NOT UNKNOWN also evaluates to UNKNOWN. As a result, all rows are filtered out and the query returns an empty set.
Possible solutions include:
select s.status
from mstatus s
left join people p
on p.status=s.status
where p.status is null
or use not exists
Try using joins to solve this
select g.*, e.*,c.* from
grade g inner join evaluation e on
g.ID_COURSES <> e.ID_COURSES and g.year <> e.year
inner join COURSE c on c.ID_COURSES = g.ID_COURSES
;

Combine results of multiple SQL queries (UNION not possible because column names are different)

I want to make a notifications page which shows notifications about a variety of things, like new followers, new likes, new comments etc. I want to display a list that shows all of these things in chronological order.
My tables look like this:
COMMENT
1 comment__id
2 comment__user_id
3 comment__snap__id
4 comment__text
5 comment_add_time
LIKE
1 like__id
2 like__user__id
3 like__snap__id
4 like__like_time
FOLLOW
1 follow__id
2 follower__user__id
3 followed__user__id
4 follow__follow_time
5 follow__request_status
I would load the followers of a user with a query like this:
try {
$select_followers_query = '
SELECT follow.follower__user__id, follow.followed__user__id, follow.follow__request_status, user.user__id, user.user__username, user.user__profile_picture, user.privacy
FROM follow
JOIN user ON(follow.follower__user__id = user.user__id)
WHERE followed__user__id = :followed__user__id';
$prep_select_followers = $conn->prepare($select_followers_query);
$prep_select_followers->bindParam(':followed__user__id', $get_user__id, PDO::PARAM_INT);
$prep_select_followers->execute();
$followers_result = $prep_select_followers->fetchAll();
$followers_count = count($followers_result);
}
catch(PDOException $e) {
$conn = null;
echo $error;
}
Next, I get the results like this:
foreach($followers_result AS $followers_row) {
$follower_user_id = $followers_row['follower__user__id'];
// the rest of the variables will come here...
}
I will have separate SQL queries like the one above which each load something. The example above loads the followers, another query will load the comments etc. I want to display the results of all of these queries and display them in chronological order, like this:
#user_1 liked your photo
#user_4 started following you
#user_2 commented on your photo
etc...
How can I achieve this? SQL UNION requires the tables to have the same number of columns and the selected columns must have the same name. I don't have all that. Moreover, every kind of result (follower, comment or like) will have different markups. A follower notification will have a follow button, a comment notification will have a button that redirects to the photo that was liked etc.
SQL UNION requires the tables to have the same number of columns and the selected columns must have the same name.
No, it doesn't. Here table "a" has two columns, integer and varchar.
create table a (
a_id integer,
a_desc varchar(10)
);
insert into a values (1, 'aaaaaaaa'), (2, 'bbbbbbbb');
Table "b" has three columns, varchar, date, and char.
create table b (
b_id varchar(10),
created_date date,
unused char(1)
);
insert into b values ('xyz', '2014-01-01', 'x'), ('tuv', '2014-01-13', 'x');
The SQL union operator only requires that the SELECT clauses (not tables) have the same number of columns, and that they be of compatible data types. You can usually cast incompatible types to something more useful.
-- SELECT clause has three columns, but table "a" has only two.
-- The cast is for illustration; MySQL can union an integer with a
-- varchar without a cast.
--
select cast(a_id as char) as col_1, a_desc as col_2, null as col_3
from a
union all
-- Note that these columns don't have the same names as the columns
-- above.
select b_id, null, created_date
from b;
You can use a single column for date and varchar, but it's usually not a good idea. (Mixing dates with something that's clearly not a date is usually not a good idea.)
select cast(a_id as char) as col_1, a_desc as col_2
from a
union all
select b_id, created_date
from b;
You can use UNION but you'll need to use 'AS' to give columns the same name.
You'll also need to add a line like this to each select:
, 'comment' as Type FROM comment
and:
, 'follow' as Type FROM follow

Retrieving Data From Associated Toxi Table

I'm retrieving my data for part of my site with a typical MySQL query and echoing out the results from various fields etc etc from my main table whose structure is not important but which has a unique id which is 'job_id'
In order to have multiple catagories associated with that 'job_id' i have employed a toxi solution which associates catgories to each 'job_id'.
TABLE `tags` (
`tag_id` INT NOT NULL AUTO_INCREMENT,
`tag_name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`tag_id`)
)
CREATE TABLE `tag_relational` (
`job_id` INT NOT NULL,
`tag_id` INT NOT NULL
)
What i want to do is, when i echo out the info from the main table (using 'job_id') i also want to echo all the catagories which that job_id is matched against.
The query below only returns the first catagory(tag_name) that the job_id is listed against, when it should be up to six (at the moment):
$query = "SELECT * FROM tags t
JOIN tag_relational r
ON t.tag_id=r.tag_id
WHERE r.job_id = $job_id";
$result=mysql_query($query) or die(mysql_error());
$cats=mysql_fetch_assoc($result);
In my code i'm using this to echo out the matched catagories:
<?php echo $cats['tag_name'];?>
Can someone explain how i can get ALL the catagory names to echo out rather than just the first?
Thanks
Dan
BTW, apologies to mu is too short who kindly answered my question when i had dummy/less complete information above.
If you just want to list the category names, then you could use group_concat sort of like this:
select b.*,
group_concat(c.category_name order by c.category_name separator ' ,') as cats
from business b
join tbl_works_categories w on b.id = w.bus_id
join categories c on w.category_id = c.category_name
where ...
group by b.id
You'd need a proper WHERE clause of course. That will give you the usual stuff from business and the category names as a comma delimited list in cats.
If you need the category IDs as well, then two queries might be better: one to get the business information and a second to collect the categories:
select w.bus_id, c.category_id, c.category_name
from tbl_works_categories w
join categories c
where w.bus_id IN (X)
where X is a comma delimited list of business ID values. Then you'd patch things up on the client side.

PHP/Mysql: read data field value from lookup tables (split array)

I have 1 Mysql database with 2 tables:
DOCUMENTS
...
- staffID
.....
STAFF
- ID
- Name
The DOCUMENTS table assigns each document to a single or multiple users from the STAFF table therefore the staffID in the DOCUMENTS table consists of a comma separated array of staff ID's for example (2, 14).
I managed to split the array into individual values:
2
14
but rather than having the ID numbers I would like to have the actual names from the STAFF table - how can I achieve this. Any help would be greatly appreciated - please see my current code below.
$result = mysql_query("SELECT
organizations.orgName,
documents.docName,
documents.docEntry,
documents.staffID,
staff.Name,
staff.ID
FROM
documents
INNER JOIN organizations ON (documents.IDorg = organizations.IDorg)
INNER JOIN staff ON (documents.staffID = staff.ID)
")
or die(mysql_error());
while($row = mysql_fetch_array($result)){
$splitA = $row['staffID'];
$resultName = explode(',', $splitA );
$i=0;
for($i=0;$i<count($resultName);$i++)
{
echo "<a href='staffview.php?ID=".$row['docName'].
"'>". $resultName[$i]."</a><br>";
}
echo '<hr>';
}
It looks like your existing code might work where documents.staffID = staff.ID - that is where there is just a single staffID associated with the document?
You'd be better off adding a table to model the relationships between documents and staff separately from either, and removing or deprecating the staffID field in the documents table. You'd need something like
CREATE TABLE document_staff (
document_id <type>,
staff_id <type>
)
You can include compound indexes with ( document_id, staff_id ) and ( staff_id, document_id ) if you have lots of data and/or you want to traverse the relationship efficiently in both directions.
(You don't mention data types for your identity fields, but documents.staffID appears to be some sort of varchar based on what you say - perhaps you could use an integer type for these instead?)
But you can probably achieve what you want using the existing schema and the MySQL FIND_IN_SET function:
SELECT
organizations.orgName,
documents.docName,
documents.docEntry,
documents.staffID,
staff.Name,
staff.ID
FROM
documents
INNER JOIN organizations ON (documents.IDorg = organizations.IDorg)
INNER JOIN staff ON ( FIND_IN_SET( staff.ID, documents.staffID ) > 0 )
MySQL set types have limitations - maximum membership size of 64 for example - but may be sufficient for your needs.
If it was me though, I'd change the model rather than use FIND_IN_SET.
Thank you so much for you answer - greatly appreciated!
My table setup is:
DOCUMENTS:
CREATE TABLE documents (
docID int NOT NULL,
docTitle mediumblob NOT NULL,
staffID varchar(120) NOT NULL,
Author2 int,
IDorg int,
docName varchar(150) NOT NULL,
docEntry int AUTO_INCREMENT NOT NULL,
/* Keys */
PRIMARY KEY (docEntry)
) ENGINE = MyISAM;
STAFF:
CREATE TABLE staff (
ID int AUTO_INCREMENT NOT NULL,
Name varchar(60) NOT NULL,
Organization varchar(20),
documents varchar(150),
Photo mediumblob,
/* Keys */
PRIMARY KEY (ID)
) ENGINE = MyISAM;
The DOCUMENTS table reads via a lookup table (dropdown) from the STAFF table so that I can assign multiple staff members to a document. So I can access the staffID array in the DOCUMENTS table and split that and I wonder if there is a way to then associate the staffID with the staff.Name and print out the staff Name rather than the ID in the results of the query. Thanks again!

Categories