MySQL Unique Identifiers on Column Names of UNION Query - php

I have two different tables that share an 'is_featured' column. I need to select all content that is checked 'is_featured' and sort the results by 'date_display' desc.
PHOTOS
item_name | date_display | is_featured
photo1 | 01-02-13 | yes
photo2 | 02-12-13 | yes
photo6 | 06-24-12 | no
photo23 | 09-24-12 | no
VIDEOS
item_name | date_display | is_featured
video5 | 01-14-13 | no
video10 | 03-09-13 | no
video30 | 03-21-13 | yes
video17 | 11-14-12 | yes
DESIRED RESULTS - All FEATURED CONTENT Sorted by Date DESC
item_name | date_display | is_featured
video30 | 03-21-13 | yes
photo2 | 02-12-13 | yes
photo1 | 01-02-13 | yes
video17 | 11-14-12 | yes
I'm able to get my desired result with this UNION query:
SELECT *
FROM (SELECT item_name, date_display
FROM photos
WHERE is_featured='yes'
UNION
SELECT item_name, date_display
FROM videos
WHERE is_featured='yes'
) x
ORDER BY date_display DESC
What I need now is to be able to add unique identifiers to the item_names of each table. For examples: photos.item_name and videos.item_name.
Is that possible with the query I have?
I ultimately need to do something like the following:
If (item_name is from Photos table) { do this }

Try something like:
...
FROM (SELECT item_name, date_display, 'photo' AS media_type
FROM photos...
and similarly for the video subquery. This will create a column media_type in your result set that is 'photo' for the photos, and 'video' for the videos.
Your result set would look like this:
item_name | date_display | media_type
video30 | 03-21-13 | video
photo2 | 02-12-13 | photo
photo1 | 01-02-13 | photo
video17 | 11-14-12 | video
Exactly how you check that value depends on how you handle your query results, but here's some Code Igniter-like pseudo-code provided for concreteness. You can adapt it to whatever your situation calls for:
foreach($query->result() as $row) {
if ($row->media_type == 'photo') {
$featured_photos[$row->item_name] = $row;
}
else {
$featured_videos[$row->item_name] = $row;
}
}
That example is a little silly because it just undoes the work of the union in your query, but the point is that once you get your results back you can use the media_type field to differentiate where the items came from.

Related

MySQL breaking a large table into smalller related tables

Is it possible to break a large MySQL table into smaller related tables?
for instance imagine the table:
x_data--
id | offer_price | offer_text | free_gift | free_gift_category | model_name | model_description | tariff_name | tariff_rental | tariff_minutes | tariff_texts | tariff_data | retailer_name | retailer_description
is it possible to split this out into separate tables and build relationships so the resulting tables look like:
offers--
id | offer_price | offer_text | free_gift_id | model_id | tariff_id | retailer_id
free_gifts--
id | free_gift | free_gift_category_id
free_gift_categories--
id | free_gift_category
models--
id | name | description
tariffs--
id | name | rental | minutes | texts | data
retailers--
id | name | description
i.e can I do an insert on a sub select or join?
something like:
$query = "INSERT INTO retailers (name,description)
(SELECT retailer_name, retailer_description FROM x_data) as retailer,
(SELECT MAX(id) as retailer_id FROM retailers) as retailer_id,
INSERT INTO tariffs (name, rental, minutes, texts, data) as tariffs, ...."
if this is possible how would I go about it?

select count with union table sql query

I am making a search paging, i have tried to select count from three table using union but am getting error like this
Fatal error: Cannot pass parameter 2 by reference in /home/plooks/public_html/user/test.php on line 106here is my table structure
table 1 name >> blogpost
| bid | title | body | author |
|----- |------- |------------- |-------- |
| 1 | new | hello new | you |
| 2 | cast | broadcast | me |
| 3 | hack | who hack us | you |
table2 name >> forumnew
| fid | ftitle | fbody | user |
|----- |------- |------------- |-------- |
| 1 | new forum | hello new | you |
| 2 | cast me | broadcast | me |
| 3 | hack you | who hack him | us |
table3 name >> download
| did | file | disc | type |
|----- |------- |------------- |-------- |
| 1 | whoweare | hello new | php |
| 2 | cast | broadcast | html |
| 3 | hack | who hack us | c++ |
SQL QUERY
SELECT COUNT(id) FROM (
SELECT 'post' AS type, BID AS id FROM blogpost
UNION
SELECT 'jail' AS type, jid AS id FROM forumnew
UNION
SELECT 'article' AS type, TID AS id FROM download
)csl WHERE title LIKE :search OR title LIKE :search")
There is a mistake in the query, you don't have the title in the temporary table csl, so it cannot be used in the WHERE clause. Also the second OR title LIKE :search is superfluous. If you don't want to do a distinct count of the id, then you don't need the other columnns, only the title column to filter by, the result will be the same.
SELECT COUNT(*) FROM (
SELECT title FROM blogpost
UNION
SELECT ftitle AS title FROM forumnew
UNION
SELECT disc AS title FROM download
) csl WHERE title LIKE :search
or
SELECT
(SELECT COUNT(*) FROM blogpost WHERE title LIKE :search) +
(SELECT COUNT(*) FROM forumnew WHERE ftitle LIKE :search) +
(SELECT COUNT(*) FROM download WHERE disc LIKE :search)

Best way to output results from two unidentical database tables

I have two tables in my database announcements and announcements_external:
+----------+ +----------+
| table1 | | table2 |
+----------+ +----------+
| id | | id |
| catid | | eid |
| uid | | username |
| title | | source |
| text | | title |
| views | | section |
| images | | category |
| created | | text |
| modified | | views |
| pubdate | | images |
+----------+ | created |
| modified |
+----------+
In CodeIgniter framework, I want to merge them, so when I will do a foreach($results as $item), I would output them side by side, ordered by field created.
I tried this code but I know it's completly wrong with the merging:
public function get_mixed( $limit = NULL, $offset = NULL )
{
$this->db
->select('
announcements.id,
announcements.catid,
announcements.uid,
section.title AS section,
categories.title AS category,
announcements.title,
announcements.text,
announcements.views,
announcements.created,
announcements.modified,
announcements.pubdate,
announcements_external.id as eid,
announcements_external.eid,
announcements_external.source,
announcements_external.username,
announcements_external.section as esection,
announcements_external.category as ecategory,
announcements_external.title as etitle,
')
->join('categories', 'announcements.catid = categories.id', 'left')
->join('categories as section', 'categories.pid = section.id', 'left')
->join('announcements_external', 'announcements_external.id = announcements_external.id', 'right')
->order_by('created DESC, '.$this->_order_by);
$query = $this->db->get( $this->_table_name, $limit, $offset )->result();
return $query;
}
By the way, I do LEFT JOIN on categories table, which works as it should, but I thought it would be better to leave it in this code so you will see it also.
Any solution or maybe guide where I can get more information pls ? Thanks
It seems that Table1 and Table2 are separated entities so you need to use UNION ALL instead of JOIN to merge them.
(SELECT ..needed columns .. , Table1.created FROM Table1 JOIN categories ... )
UNION All
(SELECT ..needed columns .. , Table2.created FROM Table2 JOIN categories ... )
ORDER BY created ;
You will need to use fake columns aliases for nonidentical columns, if necessary.

MySQL Dynamic Select Box

I have two tables in MySQL, (and using PHP) which look similar to below:
------------------------
| |
| sizes | <--- This table is what populates the Select Box
| |
------------------------
| id | name |
| | |
| 1 | Small |
| 2 | Medium |
| 3 | Large |
------------------------
----------------------------------------
| |
| user_entries | <--- This table relates to above by "size_id"
| |
----------------------------------------
| id | user_id | size_id |
| | | |
| 1 | 25 | 2 |
| 2 | 12 | 3 |
| 3 | 15 | 3 |
----------------------------------------
My question is: How can I write my SELECT statement to both populate a select box with all the size options (Small, Med, Large) AND pre-select the option based on the user's preference.
For example, for the user with user_id=25, the HTML would look like:
<select>
<option>Small</option>
<option selected="selected">Medium</option>
<option>Large</option>
</select>
SQL is:
SELECT s.id, s.name, ue.id as UserSelected
FROM sizes s
LEFT JOIN user_entries ue ON s.id=ue.size_id AND ue.user_id=XXX
ORDER BY s.id
(Set the order as you want)
The, when you run through the results, if "UserSelected" is not NULL (i.e. has a value) then you have the selected entry.
SQL tips: try to keep column names the same between tables, so that "size_id" is the name of the id field in the size table as well as the foreign key in user_entries table; this way, you wouldn't have two "id" columns in this query that would cause problems.
You also probably don't need the "id" column in the user_entries table as you'll always search/update based on user_id? Just one less column/index to handle if you don't need it.
// get size id from user entries table based on user id
$result2= mysql_query("SELECT size_id from user_entries where user_id='$user_id'");
$row2 = mysql_fetch_assoc($result2);
$sel_size_id =$row2['size_id'];
//dropdownlist query
$query="SELECT name,id FROM sizes";
/* You can add order by clause to the sql statement if the names are to be displayed in alphabetical order */
$result = mysql_query ($query);
//populate the dropdownlist
while($row = mysql_fetch_assoc($result)) {
//determine if the size id is selected
$selected = ($row['size_id '] == $sel_size_id ) ? ' selected="selected" ' : NULL;
echo '<option value="' . $row['size_id']. '"' . $selected . '>'.$row['name'].'</option>\n';
}

Show database entries separated by comma

I have one field in the backend, where I input IDs separated by comma - ID1, ID2, ID3....These are videos in fact. All ids are stored in the field product_videos in the database (as they are typed).
How can I echo these id's on the frontend so they all show for the product?
Storing comma separated data in one data field is a bad idea. It is a real pain to manipulate, so you should really consider revising your db structure.
You haven't shown your data structure, so I'll give a basic example and then explain how it can be improved. My example assumes product_videos is linked to particular users:
table: `users`
| user_id | user_name | product_videos |
|---------|-----------|----------------|
| 1 | User1 | 1,2,3,4,6,7 |
| 2 | User2 | 5 |
You would maybe run a query
SELECT `product_videos` FROM `users` WHERE `user_name` = 'User1'
This would give you one row, with a comma separate value - you would then need to use something like PHP's explode() to convert it into an array and then loop through that array. That is a very bad method (and it will only become harder as you try to do more advanced things).
Instead, it would be easier to use a link table. Imagine:
table: `users`
| user_id | user_name |
|---------|-----------|
| 1 | User1 |
| 2 | User2 |
table: `videos`
| video_id | user_id |
|-----------|---------|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
| 6 | 1 |
| 7 | 1 |
In this example, each video is a separate row in a db table (and each video is linked to an existing user). Each row is readily able to be handled independently. This makes it really easy to handle extra data for each video, such as a title, runtime length, date of uploading, etc.
You would then need to run a JOIN query. e.g.
SELECT `videos`.`video_id` FROM `videos`
INNER JOIN `users` ON `users`.`user_id` = `videos`.`user_id`
WHERE `users`.`user_name` = 'User1'
In PHP, you would do something like:
$q = mysql_query("SELECT `videos`.`video_id` FROM `videos` INNER JOIN `users` ON `users`.`user_id` = `videos`.`user_id` WHERE `users`.`user_name` = 'User1'");
while ($row = mysql_fetch_assoc($q)) {
echo "VIDEO ID = " . $row["video_id"] . "<br/>";
}

Categories