using union on two tables but renaming the field - php

I have two tables that have an id field with the same name. I didn't think I'd ever need to mix the two but there's one page where I need to. I can't join the tables because they both have completely separate data and no fields in common.
I can union them but the ID field is the same name and many identical numbers (which do not relate). I can't change the name in the tables but I need the field names to be different when put into a variable (using PHP).
I tried something like this:
SELECT date, id as id1
FROM football
UNION
SELECT date, id as id2
FROM basketball
ORDER BY date
But that just gives me one field (id1). I need the result to be in such a way that I can do this:
foreach ($rows as $row) {
if (!empty($row['id1'])) {
$id = $row['id1'];
$sport = "football";
} else {
$id = $row['id2'];
$sport = "basketball";
}
echo "my number is $id and I play $sport";
}

From MySQL Union Syntax
The column names from the first SELECT statement are used as the
column names for the results returned.
You could assign sport in your query:
SELECT date, id, 'football' as sport
FROM football
UNION
SELECT date, id, 'basketball' as sport
FROM basketball
ORDER BY date

Related

mysql - group results by id and print

I have "reservation" table (mySql) that contain number of columns: res_id, hotel_id, hotel_name, from_date, to_date.
I would like to select and print html table for each hotel (i'm using PHP). the result should be a title - the name of the hotel, and bellow it a list of reservation for the specific hotel.
I can do GROUP BY:
Select * FROM reservation GROUP BY hotel_id
I'm not sure if it's the right way to do it, and how do i print the results without checking all the time if the hotel_id was changed?
Thank you in advanced
GROUP BY is definitely NOT the right way to approach this. One method would be:
SELECT *
FROM reservation
ORDER BY hotel_id;
You would then loop through the result sets. When the hotel name changes, you would put in the title of the hotel.
Note: This is a poor data model if it has both the hotel id and name in reservation. This would normally be in hotel and you would connect the tables using JOIN:
SELECT h.hotel_name, r.*
FROM hotels h JOIN
reservation r
ON r.hotel_id = h.hotel_id
ORDER BY hotel_id;
Using a LEFT JOIN, you can even get hotels with no reservations.
How is it that the hotel_id would change? As per your question it seems that hotel_id is a column made for join with a "hotels" table, isn't it?
Regarding the "group by", why would you group by hotel? This would make you loose reservations data, unless you were using some sort of group_concat.
If you want to get the reservations from a specific hotel you could loop through your hotels table and inside your loop you can do:
SELECT * FROM reservations WHERE hotel_id='QUERIED_HOTEL_ID'
Then show the results.
Or you could simply
SELECT * FROM reservations
And when you get the fetched results you can make a multidimensional php array with 'hotel_id' as top level key and 'res_id' as secondary, like this:
$reservations_by_hotel = [];
do {
$resId = $row['res_id'];
$hotelId = $row['hotel_id'];
$reservations_by_hotel[$hotelId][$resId] = $row;
} while ($row = $result->fetch_assoc());

SELECT DISTINCT multiple values from a single cell

Let's say I have the following table, called test:
Executing the query SELECT DISTINCT category FROM test ORDER BY category; will output:
When changing a value as follows:
…and calling the query SELECT DISTINCT category FROM test ORDER BY category; again, I'll get:
But I want to get the following instead:
Is there a way to do this in SQL? Or should I do this directly in my PHP?
You should have 3 tables here. One will hold the the categories, the other one will hold the items and the final one will hold the relations between categories and items (it is also known as associative table):
categories: id name
items: id name
categories_items: category_id item_id
Your query in this case will become:
SELECT id, name
FROM categories
ORDER BY name;
If you want to get all items from a category you could do:
SELECT id, name
FROM items
JOIN categories_items
ON items.id = categories_items.item_id
AND categories_items.category_id = 4;
You should definetely normalize your tables but if you still insist on this table structure, you can try this query:
WITH CatChar(aChar, remain) AS (
SELECT LEFT(category,1), RIGHT(category, LEN(category)-1)
FROM test WHERE LEN(category)>0
UNION ALL
SELECT LEFT(remain,1), RIGHT(remain, LEN(remain)-1) FROM CatChar
WHERE LEN(remain)>0
)
SELECT DISTINCT aChar FROM CatChar
(Assuming your all category names are just one char length, otherwise you should reorganeze LEFT(...) part to split according to your separator)

How do I pinpoint correct result in MYSQL Query when using Join and the 2 tables have field with same name?

I have a join and the result of the join is correct, but then I want to display a variable, but it's not in variable format like $variable, it's in the format $row['field'], however, it doesn't display the correct value because the field name is in both tables.
Sometimes it displays the left one, sometimes it displays the right one. i don't know how to force it to display the one i want.
So for example i have this query:
SELECT
user_table.*, user_groups.*
FROM
user_table
LEFT JOIN user_groups ON user_groups.groupid = user_table.usergroup
WHERE
user_table.client = "0"
AND user_table.usergroup != "1"
ORDER BY
user_groups.name ASC
Not going to put in every field, because there are too many, just a few to get the idea.
user_table:
userid, username, usergroup, fname, sname, company
user_groups:
groupid, name, userid
The JOIN will have a result like the following:
userid username usergroup fname sname company groupid name userid1
1129 whatever 2286 first last abc 2286 abc 0
Then i begin to echo all the fields like so:
while ($row=mysql_fetch_assoc($result)) {
echo $row['username']." ".$row['userid']." ".$row['company']." ".$row['fname']." ".$row['sname']." ".$row['username'];
}
All the data will be correct except the userid. it will use the zero(0) instead of the 1129 which is the one i want.
I have tried all of the following for the userid echo:
$row['userid']
$row['userid0']
$row['userid1']
$row['userid[0]']
$row['userid[1]']
$row['userid'][0]
$row['userid'][1]
Nothing works. it either displays the wrong one from the result, or displays nothing.
PHP tries to map the column names into key => value pairs. If there is a column with a duplicate name, then you'll only get one.
Map out second userid columns in MySQL using the AS keyword (http://www.w3schools.com/sql/sql_alias.asp) to give the second userid field a different name.
SELECT
user_table.*, user_groups.groupid, user_groups.name, user_groups.userid AS group_userid
FROM
user_table
LEFT JOIN user_groups ON user_groups.groupid = user_table.usergroup
WHERE
user_table.client = "0"
AND user_table.usergroup != "1"
ORDER BY
user_groups.name ASC
You can then access the two fields like this:
$row['userid']; // client.userid
$row['group_userid']; // user_groups.userid

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

Echo results of a complicated INNER JOIN query with multiple tables

This is my first question here. I have a complicated SQL database and I need to join different tables which have the same column names.
"event" is a sports match. It contains tournament_stageFK which is linked to tournament_stage table, which contains tournamentFK which is linked to tournament table, which contains tournament_templateFK which is linked to tournament_template table, which contains sportFK which is linked to sport table.
So in order to find out what sport the match is from, I need to do an inner join, otherwise I'd have to open the database millions of times. The only way to do it is this, but I don't know how to display the results. My poor attempt to echo the results is below:
$SQL = "SELECT sport.name,
country.name,
tournament_template.name,
tournament.name,
tournament_stage.name,
event.*
FROM tournament_template
INNER JOIN sport
ON tournament_template.sportFK = sport.id
INNER JOIN tournament ON tournament.tournament_templateFK = tournament_template.id
INNER JOIN tournament_stage ON tournament_stage.tournamentFK = tournament.id
INNER JOIN event ON event.tournament_stageFK = tournament_stage.id
INNER JOIN country ON tournament_stage.countryFK = country.id
WHERE DATE(event.startdate) = CURRENT_DATE()
ORDER BY sport.name ASC,
country.name ASC,
tournament_stage.name ASC,
event.startdate ASC";
$result = mysql_query($SQL);
while($get=mysql_fetch_array($result))
{
echo $result['event.name'];
echo "<br>";
}
Your result is fetched as an array indexed by column name, which is "name" for several of your columns... the table name sport, country, template, etc is not part of the returned index. So you need to provide column names that will be unique
Set an alias for each of your columns (e.g. SELECT sport.name AS sport_name) then reference it by its alias within your echo (e.g. $result['sport_name']).
You need to use column aliases and access those in your fetch call. Instead of event.*, be explicit about the columns you need:
$SQL = "SELECT sport.name AS sportname,
country.name AS countryname,
tournament_template.name AS templatename,
tournament.name AS tournamentname,
tournament_stage.name AS stagename,
/* Use explicit column names instead of event.* */
event.name AS eventname,
event.someothercol AS someother
FROM tournament_template
...etc...
...etc...";
// Later...
while($row=mysql_fetch_array($result))
{
echo $row['eventname'];
echo "<br>";
}

Categories